|
28 | 28 | from django.utils.translation import gettext as _
|
29 | 29 | from django.contrib.auth.models import Group
|
30 | 30 | from geonode.groups.models import GroupProfile
|
| 31 | +from geonode.people import Roles |
31 | 32 |
|
32 | 33 | from geonode.metadata.settings import MODEL_SCHEMA
|
33 | 34 | from geonode.base.models import (
|
|
40 | 41 | LinkedResource,
|
41 | 42 | Thesaurus,
|
42 | 43 | ThesaurusKeyword,
|
| 44 | + ContactRole, |
| 45 | + ThesaurusKeyword, |
43 | 46 | )
|
44 | 47 | from geonode.settings import PROJECT_ROOT
|
45 | 48 | from geonode.metadata.handlers.base import (
|
|
61 | 64 | from geonode.metadata.handlers.contact import ContactHandler
|
62 | 65 | from geonode.metadata.handlers.thesaurus import TKeywordsHandler
|
63 | 66 | from geonode.metadata.handlers.sparse import SparseHandler
|
64 |
| -from geonode.tests.base import GeoNodeBaseTestSupport |
65 | 67 | from geonode.resource.utils import KeywordHandler
|
| 68 | +from geonode.metadata.handlers.contact import ContactHandler, ROLE_NAMES_MAP |
| 69 | + |
| 70 | +from geonode.tests.base import GeoNodeBaseTestSupport |
66 | 71 |
|
67 | 72 |
|
68 | 73 | class HandlersTests(GeoNodeBaseTestSupport):
|
@@ -1343,3 +1348,202 @@ def test_hkeywords_handler_update_resource_with_null_empty_keywords(self):
|
1343 | 1348 | keyword_names = [keyword.name for keyword in keywords]
|
1344 | 1349 | expected_keywords = ["valid keyword"]
|
1345 | 1350 | self.assertCountEqual(keyword_names, expected_keywords)
|
| 1351 | + |
| 1352 | + # Tests for contact handler |
| 1353 | + @patch("geonode.metadata.handlers.contact.reverse") |
| 1354 | + def test_contact_handler_update_schema(self, mock_reverse): |
| 1355 | + # Mock reverse function |
| 1356 | + mock_reverse.return_value = "/mocked/url" |
| 1357 | + |
| 1358 | + # Call update_schema |
| 1359 | + updated_schema = self.contact_handler.update_schema(self.fake_schema, self.context, self.lang) |
| 1360 | + |
| 1361 | + self.assertIn("contacts", updated_schema["properties"]) |
| 1362 | + |
| 1363 | + # Check if all roles are included in the contacts |
| 1364 | + contacts = updated_schema["properties"]["contacts"]["properties"] |
| 1365 | + for role in Roles: |
| 1366 | + rolename = ROLE_NAMES_MAP.get(role, role.name) |
| 1367 | + self.assertIn(rolename, contacts) |
| 1368 | + |
| 1369 | + contact = contacts[rolename] |
| 1370 | + self.assertIn("type", contact) |
| 1371 | + |
| 1372 | + if role.is_multivalue: |
| 1373 | + self.assertEqual(contact.get("type"), "array") |
| 1374 | + self.assertIn("minItems", contact) |
| 1375 | + self.assertIn("properties", contact["items"]) |
| 1376 | + if role.is_required: |
| 1377 | + self.assertEqual(contact["minItems"], 1) |
| 1378 | + else: |
| 1379 | + self.assertEqual(contact["minItems"], 0) |
| 1380 | + else: |
| 1381 | + self.assertEqual(contact.get("type"), "object") |
| 1382 | + self.assertIn("properties", contact) |
| 1383 | + # Assert 'id' field is required if the role is required |
| 1384 | + if role.is_required: |
| 1385 | + self.assertIn("id", contact["required"]) |
| 1386 | + else: |
| 1387 | + self.assertNotIn("id", contact["required"]) |
| 1388 | + |
| 1389 | + def test_contact_handler_get_jsonschema_instance(self): |
| 1390 | + |
| 1391 | + field_name = "contacts" |
| 1392 | + |
| 1393 | + # Create an author role for testing |
| 1394 | + author_role = get_user_model().objects.create_user( |
| 1395 | + "author_role", "[email protected]", "new_fake_user_password", is_active=True |
| 1396 | + ) |
| 1397 | + |
| 1398 | + # Assign metadata author role |
| 1399 | + ContactRole.objects.create( |
| 1400 | + resource=self.resource, role=ROLE_NAMES_MAP[Roles.METADATA_AUTHOR], contact=author_role |
| 1401 | + ) |
| 1402 | + |
| 1403 | + # Call the method |
| 1404 | + result = self.contact_handler.get_jsonschema_instance( |
| 1405 | + self.resource, field_name, self.context, self.errors, self.lang |
| 1406 | + ) |
| 1407 | + |
| 1408 | + # Assert the output structure and content |
| 1409 | + self.assertIn(ROLE_NAMES_MAP[Roles.OWNER], result) |
| 1410 | + self.assertIn(ROLE_NAMES_MAP[Roles.METADATA_AUTHOR], result) |
| 1411 | + |
| 1412 | + # Check owner which is defined in the setUp method as test_user |
| 1413 | + owner_entry = result[ROLE_NAMES_MAP[Roles.OWNER]] |
| 1414 | + self.assertEqual(owner_entry["id"], str(self.test_user.id)) |
| 1415 | + self.assertEqual(owner_entry["label"], f"{self.test_user.username}") |
| 1416 | + |
| 1417 | + # Check metadata author |
| 1418 | + author_entry = result[ROLE_NAMES_MAP[Roles.METADATA_AUTHOR]] |
| 1419 | + self.assertEqual(len(author_entry), 1) # Assuming it's a multivalue role |
| 1420 | + self.assertEqual(author_entry[0]["id"], str(author_role.id)) |
| 1421 | + self.assertEqual(author_entry[0]["label"], f"{author_role.username}") |
| 1422 | + |
| 1423 | + def test_contact_handler_update_resource(self): |
| 1424 | + |
| 1425 | + field_name = "contacts" |
| 1426 | + |
| 1427 | + # Create a new owner instead of the initial test_user which is already defined as the owner |
| 1428 | + new_owner = get_user_model().objects.create_user( |
| 1429 | + "new_owner", "[email protected]", "new_owner_password", is_active=True |
| 1430 | + ) |
| 1431 | + |
| 1432 | + # Create an author role for testing |
| 1433 | + author_role = get_user_model().objects.create_user( |
| 1434 | + "author_role", "[email protected]", "new_fake_user_password", is_active=True |
| 1435 | + ) |
| 1436 | + |
| 1437 | + # Prepare the JSON instance for updating |
| 1438 | + json_instance = { |
| 1439 | + field_name: { |
| 1440 | + ROLE_NAMES_MAP[Roles.OWNER]: {"id": str(new_owner.id), "label": f"{new_owner.username}"}, |
| 1441 | + ROLE_NAMES_MAP[Roles.METADATA_AUTHOR]: [ |
| 1442 | + {"id": str(author_role.id), "label": f"{author_role.username}"}, |
| 1443 | + ], |
| 1444 | + } |
| 1445 | + } |
| 1446 | + |
| 1447 | + # Call the method |
| 1448 | + self.contact_handler.update_resource(self.resource, field_name, json_instance, self.context, self.errors) |
| 1449 | + |
| 1450 | + # Assert the owner has been updated |
| 1451 | + self.assertEqual(self.resource.owner, new_owner) |
| 1452 | + |
| 1453 | + # Assert that the author role has been updated |
| 1454 | + contacts = self.resource.__get_contact_role_elements__(ROLE_NAMES_MAP[Roles.METADATA_AUTHOR]) |
| 1455 | + |
| 1456 | + self.assertEqual(len(contacts), 1) |
| 1457 | + self.assertEqual(contacts[0].id, author_role.id) |
| 1458 | + |
| 1459 | + # Tests for thesaurus handler |
| 1460 | + @patch("geonode.metadata.handlers.thesaurus.reverse") |
| 1461 | + @patch("geonode.metadata.handlers.thesaurus.TKeywordsHandler.collect_thesauri") |
| 1462 | + def test_tkeywords_handler_update_schema_with_thesauri(self, mock_collect_thesauri, mocked_endpoint): |
| 1463 | + |
| 1464 | + # fake_schema definition which includes the "category" field |
| 1465 | + schema = { |
| 1466 | + "properties": { |
| 1467 | + "category": {"type": "string", "title": "category", "maxLength": 255}, |
| 1468 | + "fake_field": {"type": "string", "title": "fake_field", "maxLength": 255}, |
| 1469 | + } |
| 1470 | + } |
| 1471 | + |
| 1472 | + # Mock data for collect_thesauri |
| 1473 | + mock_collect_thesauri.return_value = { |
| 1474 | + "3-2-4-3-spatialscope": { |
| 1475 | + "id": 1, |
| 1476 | + "card": {"minItems": 0, "maxItems": 1}, |
| 1477 | + "title": "Spatial scope", |
| 1478 | + "description": "Administrative level that the data set intends to cover.", |
| 1479 | + }, |
| 1480 | + "3-2-4-1-gemet-inspire-themes": { |
| 1481 | + "id": 2, |
| 1482 | + "card": {"minItems": 1}, |
| 1483 | + "title": "GEMET - INSPIRE themes, version 1.0", |
| 1484 | + "description": "GEMET - INSPIRE themes, version 1.0", |
| 1485 | + }, |
| 1486 | + } |
| 1487 | + |
| 1488 | + # Mock reverse to return a URL |
| 1489 | + mocked_endpoint.side_effect = lambda name, kwargs: f"/mocked/url/{kwargs['thesaurusid']}" |
| 1490 | + |
| 1491 | + # Call the method |
| 1492 | + updated_schema = self.tkeywords_handler.update_schema(schema, context={}, lang="en") |
| 1493 | + |
| 1494 | + # Assert tkeywords property is added |
| 1495 | + tkeywords = updated_schema["properties"].get("tkeywords") |
| 1496 | + self.assertIsNotNone(tkeywords) |
| 1497 | + self.assertEqual(tkeywords["type"], "object") |
| 1498 | + self.assertEqual(tkeywords["title"], "Keywords from Thesaurus") |
| 1499 | + |
| 1500 | + # Assert thesaurus structure for "3-2-4-3-spatialscope" |
| 1501 | + thesaurus = tkeywords["properties"]["3-2-4-3-spatialscope"] |
| 1502 | + self.assertEqual(thesaurus["type"], "array") |
| 1503 | + self.assertEqual(thesaurus["title"], "Spatial scope") |
| 1504 | + self.assertEqual( |
| 1505 | + thesaurus["description"], |
| 1506 | + "Administrative level that the data set intends to cover.", |
| 1507 | + ) |
| 1508 | + self.assertEqual(thesaurus["minItems"], 0) |
| 1509 | + self.assertEqual(thesaurus["maxItems"], 1) |
| 1510 | + self.assertEqual( |
| 1511 | + thesaurus["ui:options"]["geonode-ui:autocomplete"], |
| 1512 | + "/mocked/url/1", |
| 1513 | + ) |
| 1514 | + |
| 1515 | + # Assert thesaurus structure for "3-2-4-1-gemet-inspire-themes" |
| 1516 | + thesaurus = tkeywords["properties"]["3-2-4-1-gemet-inspire-themes"] |
| 1517 | + self.assertEqual(thesaurus["type"], "array") |
| 1518 | + self.assertEqual(thesaurus["title"], "GEMET - INSPIRE themes, version 1.0") |
| 1519 | + self.assertEqual( |
| 1520 | + thesaurus["description"], |
| 1521 | + "GEMET - INSPIRE themes, version 1.0", |
| 1522 | + ) |
| 1523 | + self.assertEqual(thesaurus["minItems"], 1) |
| 1524 | + self.assertNotIn("maxItems", thesaurus) |
| 1525 | + self.assertEqual( |
| 1526 | + thesaurus["ui:options"]["geonode-ui:autocomplete"], |
| 1527 | + "/mocked/url/2", |
| 1528 | + ) |
| 1529 | + |
| 1530 | + @patch("geonode.metadata.handlers.thesaurus.TKeywordsHandler.collect_thesauri") |
| 1531 | + def test_tkeywords_handler_update_schema_no_thesauri(self, mock_collect_thesauri): |
| 1532 | + |
| 1533 | + schema = { |
| 1534 | + "properties": { |
| 1535 | + "category": {"type": "string", "title": "category", "maxLength": 255}, |
| 1536 | + "fake_field": {"type": "string", "title": "fake_field", "maxLength": 255}, |
| 1537 | + } |
| 1538 | + } |
| 1539 | + |
| 1540 | + # Mock empty thesauri |
| 1541 | + mock_collect_thesauri.return_value = {} |
| 1542 | + |
| 1543 | + # Call the method |
| 1544 | + updated_schema = self.tkeywords_handler.update_schema(schema, context={}, lang="en") |
| 1545 | + |
| 1546 | + # Assert tkeywords property is hidden |
| 1547 | + tkeywords = updated_schema["properties"].get("tkeywords") |
| 1548 | + self.assertIsNotNone(tkeywords) |
| 1549 | + self.assertEqual(tkeywords["ui:widget"], "hidden") |
0 commit comments