udata 13.0.1.dev12__py3-none-any.whl → 14.4.1.dev7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of udata might be problematic. Click here for more details.

Files changed (177) hide show
  1. udata/api/__init__.py +2 -8
  2. udata/api_fields.py +35 -4
  3. udata/app.py +30 -50
  4. udata/auth/__init__.py +29 -6
  5. udata/auth/forms.py +8 -6
  6. udata/auth/views.py +6 -3
  7. udata/commands/__init__.py +2 -14
  8. udata/commands/db.py +13 -25
  9. udata/commands/info.py +0 -16
  10. udata/commands/serve.py +3 -11
  11. udata/commands/tests/test_fixtures.py +9 -9
  12. udata/core/access_type/api.py +1 -1
  13. udata/core/access_type/constants.py +12 -8
  14. udata/core/activity/api.py +5 -6
  15. udata/core/avatars/api.py +43 -0
  16. udata/core/avatars/test_avatar_api.py +30 -0
  17. udata/core/badges/tests/test_commands.py +6 -6
  18. udata/core/csv.py +5 -0
  19. udata/core/dataservices/models.py +15 -3
  20. udata/core/dataservices/tasks.py +7 -0
  21. udata/core/dataset/api.py +2 -0
  22. udata/core/dataset/models.py +2 -2
  23. udata/core/dataset/permissions.py +31 -0
  24. udata/core/dataset/tasks.py +50 -10
  25. udata/core/discussions/models.py +1 -0
  26. udata/core/metrics/__init__.py +0 -6
  27. udata/core/organization/api.py +8 -5
  28. udata/core/organization/mails.py +1 -1
  29. udata/core/organization/models.py +9 -1
  30. udata/core/organization/notifications.py +84 -0
  31. udata/core/organization/permissions.py +1 -1
  32. udata/core/organization/tasks.py +3 -0
  33. udata/core/pages/tests/test_api.py +32 -0
  34. udata/core/post/api.py +24 -69
  35. udata/core/post/models.py +84 -16
  36. udata/core/post/tests/test_api.py +24 -1
  37. udata/core/reports/api.py +18 -0
  38. udata/core/reports/models.py +42 -2
  39. udata/core/reuse/models.py +1 -1
  40. udata/core/reuse/tasks.py +7 -0
  41. udata/core/site/models.py +2 -6
  42. udata/core/spatial/commands.py +2 -4
  43. udata/core/spatial/forms.py +2 -2
  44. udata/core/spatial/models.py +0 -10
  45. udata/core/spatial/tests/test_api.py +1 -36
  46. udata/core/user/models.py +15 -2
  47. udata/cors.py +2 -5
  48. udata/db/migrations.py +279 -0
  49. udata/features/notifications/api.py +7 -18
  50. udata/features/notifications/models.py +56 -0
  51. udata/features/notifications/tasks.py +25 -0
  52. udata/flask_mongoengine/engine.py +0 -4
  53. udata/frontend/__init__.py +3 -122
  54. udata/frontend/markdown.py +2 -1
  55. udata/harvest/actions.py +24 -9
  56. udata/harvest/api.py +30 -22
  57. udata/harvest/backends/__init__.py +21 -9
  58. udata/harvest/backends/base.py +29 -3
  59. udata/harvest/backends/ckan/harvesters.py +13 -2
  60. udata/harvest/backends/dcat.py +3 -0
  61. udata/harvest/backends/maaf.py +1 -0
  62. udata/harvest/commands.py +39 -4
  63. udata/harvest/filters.py +17 -6
  64. udata/harvest/forms.py +9 -6
  65. udata/harvest/models.py +16 -0
  66. udata/harvest/permissions.py +27 -0
  67. udata/harvest/tasks.py +3 -5
  68. udata/harvest/tests/ckan/test_ckan_backend.py +35 -2
  69. udata/harvest/tests/ckan/test_ckan_backend_errors.py +1 -1
  70. udata/harvest/tests/ckan/test_ckan_backend_filters.py +1 -1
  71. udata/harvest/tests/ckan/test_dkan_backend.py +1 -1
  72. udata/harvest/tests/dcat/udata.xml +6 -6
  73. udata/harvest/tests/factories.py +1 -1
  74. udata/harvest/tests/test_actions.py +63 -8
  75. udata/harvest/tests/test_api.py +278 -123
  76. udata/harvest/tests/test_base_backend.py +88 -1
  77. udata/harvest/tests/test_dcat_backend.py +60 -13
  78. udata/harvest/tests/test_filters.py +6 -0
  79. udata/i18n.py +11 -273
  80. udata/mail.py +5 -1
  81. udata/migrations/2025-10-31-create-membership-request-notifications.py +55 -0
  82. udata/migrations/2025-11-13-delete-user-email-index.py +25 -0
  83. udata/migrations/2025-12-04-add-uuid-to-discussion-messages.py +28 -0
  84. udata/models/__init__.py +0 -8
  85. udata/mongo/slug_fields.py +1 -1
  86. udata/rdf.py +45 -6
  87. udata/routing.py +2 -10
  88. udata/sentry.py +4 -10
  89. udata/settings.py +23 -17
  90. udata/tasks.py +4 -3
  91. udata/templates/mail/message.html +5 -31
  92. udata/tests/__init__.py +28 -12
  93. udata/tests/api/__init__.py +108 -21
  94. udata/tests/api/test_activities_api.py +36 -0
  95. udata/tests/api/test_auth_api.py +121 -95
  96. udata/tests/api/test_base_api.py +7 -4
  97. udata/tests/api/test_dataservices_api.py +29 -1
  98. udata/tests/api/test_datasets_api.py +45 -21
  99. udata/tests/api/test_organizations_api.py +192 -197
  100. udata/tests/api/test_reports_api.py +157 -0
  101. udata/tests/api/test_reuses_api.py +147 -147
  102. udata/tests/api/test_security_api.py +12 -12
  103. udata/tests/api/test_swagger.py +4 -4
  104. udata/tests/api/test_tags_api.py +8 -8
  105. udata/tests/api/test_user_api.py +13 -1
  106. udata/tests/apiv2/test_swagger.py +4 -4
  107. udata/tests/apiv2/test_topics.py +1 -1
  108. udata/tests/cli/test_cli_base.py +8 -9
  109. udata/tests/dataset/test_dataset_commands.py +4 -4
  110. udata/tests/dataset/test_dataset_model.py +66 -26
  111. udata/tests/dataset/test_dataset_rdf.py +99 -5
  112. udata/tests/dataset/test_resource_preview.py +0 -1
  113. udata/tests/frontend/test_auth.py +24 -1
  114. udata/tests/frontend/test_csv.py +0 -3
  115. udata/tests/helpers.py +37 -27
  116. udata/tests/organization/test_notifications.py +67 -2
  117. udata/tests/plugin.py +6 -261
  118. udata/tests/site/test_site_csv_exports.py +22 -10
  119. udata/tests/test_activity.py +9 -9
  120. udata/tests/test_cors.py +1 -1
  121. udata/tests/test_dcat_commands.py +2 -2
  122. udata/tests/test_discussions.py +5 -5
  123. udata/tests/test_migrations.py +181 -481
  124. udata/tests/test_notifications.py +15 -57
  125. udata/tests/test_notifications_task.py +43 -0
  126. udata/tests/test_owned.py +81 -1
  127. udata/tests/test_storages.py +25 -19
  128. udata/tests/test_topics.py +77 -61
  129. udata/tests/test_uris.py +33 -0
  130. udata/tests/workers/test_jobs_commands.py +23 -23
  131. udata/translations/ar/LC_MESSAGES/udata.mo +0 -0
  132. udata/translations/ar/LC_MESSAGES/udata.po +187 -108
  133. udata/translations/de/LC_MESSAGES/udata.mo +0 -0
  134. udata/translations/de/LC_MESSAGES/udata.po +187 -108
  135. udata/translations/es/LC_MESSAGES/udata.mo +0 -0
  136. udata/translations/es/LC_MESSAGES/udata.po +187 -108
  137. udata/translations/fr/LC_MESSAGES/udata.mo +0 -0
  138. udata/translations/fr/LC_MESSAGES/udata.po +188 -109
  139. udata/translations/it/LC_MESSAGES/udata.mo +0 -0
  140. udata/translations/it/LC_MESSAGES/udata.po +187 -108
  141. udata/translations/pt/LC_MESSAGES/udata.mo +0 -0
  142. udata/translations/pt/LC_MESSAGES/udata.po +187 -108
  143. udata/translations/sr/LC_MESSAGES/udata.mo +0 -0
  144. udata/translations/sr/LC_MESSAGES/udata.po +187 -108
  145. udata/translations/udata.pot +215 -106
  146. udata/uris.py +0 -2
  147. udata/utils.py +5 -0
  148. udata-14.4.1.dev7.dist-info/METADATA +109 -0
  149. {udata-13.0.1.dev12.dist-info → udata-14.4.1.dev7.dist-info}/RECORD +153 -166
  150. {udata-13.0.1.dev12.dist-info → udata-14.4.1.dev7.dist-info}/entry_points.txt +3 -5
  151. udata/core/followers/views.py +0 -15
  152. udata/core/post/forms.py +0 -30
  153. udata/entrypoints.py +0 -93
  154. udata/features/identicon/__init__.py +0 -0
  155. udata/features/identicon/api.py +0 -13
  156. udata/features/identicon/backends.py +0 -131
  157. udata/features/identicon/tests/__init__.py +0 -0
  158. udata/features/identicon/tests/test_backends.py +0 -18
  159. udata/features/territories/__init__.py +0 -49
  160. udata/features/territories/api.py +0 -25
  161. udata/features/territories/models.py +0 -51
  162. udata/flask_mongoengine/json.py +0 -38
  163. udata/migrations/__init__.py +0 -367
  164. udata/templates/mail/base.html +0 -105
  165. udata/templates/mail/base.txt +0 -6
  166. udata/templates/mail/button.html +0 -3
  167. udata/templates/mail/layouts/1-column.html +0 -19
  168. udata/templates/mail/layouts/2-columns.html +0 -20
  169. udata/templates/mail/layouts/center-panel.html +0 -16
  170. udata/tests/cli/test_db_cli.py +0 -68
  171. udata/tests/features/territories/__init__.py +0 -20
  172. udata/tests/features/territories/test_territories_api.py +0 -185
  173. udata/tests/frontend/test_hooks.py +0 -149
  174. udata-13.0.1.dev12.dist-info/METADATA +0 -133
  175. {udata-13.0.1.dev12.dist-info → udata-14.4.1.dev7.dist-info}/WHEEL +0 -0
  176. {udata-13.0.1.dev12.dist-info → udata-14.4.1.dev7.dist-info}/licenses/LICENSE +0 -0
  177. {udata-13.0.1.dev12.dist-info → udata-14.4.1.dev7.dist-info}/top_level.txt +0 -0
@@ -27,7 +27,7 @@ class FakeFormAPI(API):
27
27
  class OptionsCORSTest(APITestCase):
28
28
  def test_should_allow_options_and_cors(self):
29
29
  """Should allow OPTIONS operation and give cors parameters"""
30
- response = self.client.options(
30
+ response = self.options(
31
31
  url_for("api.fake-options"),
32
32
  headers={
33
33
  "Origin": "http://localhost",
@@ -38,7 +38,7 @@ class OptionsCORSTest(APITestCase):
38
38
  self.assert204(response)
39
39
  self.assertEqual(response.headers["Access-Control-Allow-Origin"], "http://localhost")
40
40
 
41
- response = self.client.options(
41
+ response = self.options(
42
42
  url_for("api.fake-options"),
43
43
  headers={
44
44
  "Origin": "http://localhost",
@@ -55,8 +55,11 @@ class OptionsCORSTest(APITestCase):
55
55
  class JSONFormRequestTest(APITestCase):
56
56
  def test_non_json_content_type(self):
57
57
  """We expect JSON requests for forms and enforce it"""
58
- response = self.client.post(
59
- url_for("api.fake-form"), {}, headers={"Content-Type": "multipart/form-data"}
58
+ response = self.post(
59
+ url_for("api.fake-form"),
60
+ {},
61
+ json=False,
62
+ headers={"Content-Type": "multipart/form-data"},
60
63
  )
61
64
  self.assert400(response)
62
65
  self.assertEqual(response.json, {"errors": {"Content-Type": "expecting application/json"}})
@@ -16,7 +16,7 @@ from udata.core.dataservices.models import Dataservice
16
16
  from udata.core.dataset.factories import DatasetFactory, LicenseFactory
17
17
  from udata.core.organization.factories import OrganizationFactory
18
18
  from udata.core.organization.models import Member
19
- from udata.core.topic.factories import TopicElementFactory, TopicFactory
19
+ from udata.core.topic.factories import ReuseFactory, TopicElementFactory, TopicFactory
20
20
  from udata.core.user.factories import AdminFactory, UserFactory
21
21
  from udata.i18n import gettext as _
22
22
  from udata.tests.helpers import assert200, assert400, assert410
@@ -99,6 +99,34 @@ class DataserviceAPITest(APITestCase):
99
99
  assert len(response.json["data"]) == 1
100
100
  assert response.json["data"][0]["id"] == str(topic_dataservice.id)
101
101
 
102
+ # filter on reuse
103
+ reuse_dataservice = DataserviceFactory()
104
+ reuse = ReuseFactory(dataservices=[reuse_dataservice])
105
+ response = self.get(url_for("api.dataservices", reuse=reuse.id))
106
+ assert200(response)
107
+ assert len(response.json["data"]) == 1
108
+ assert response.json["data"][0]["id"] == str(reuse_dataservice.id)
109
+
110
+ def test_dataservices_topic_filter_errors(self):
111
+ # non-existing
112
+ response = self.get(url_for("api.dataservices", topic="690c7f48ec85adaa376c1e93"))
113
+ assert200(response)
114
+
115
+ # not an object ID
116
+ response = self.get(url_for("api.dataservices", topic="xxx"))
117
+ assert400(response)
118
+ assert "`topic` must be an identifier" in response.json["message"]
119
+
120
+ def test_dataservices_reuse_filter_errors(self):
121
+ # non-existing
122
+ response = self.get(url_for("api.dataservices", reuse="690c7f48ec85adaa376c1e93"))
123
+ assert200(response)
124
+
125
+ # not an object ID
126
+ response = self.get(url_for("api.dataservices", reuse="xxx"))
127
+ assert400(response)
128
+ assert "`reuse` must be an identifier" in response.json["message"]
129
+
102
130
  def test_dataservice_api_create(self):
103
131
  user = self.login()
104
132
  datasets = DatasetFactory.create_batch(3)
@@ -49,8 +49,7 @@ from udata.core.user.factories import AdminFactory, UserFactory
49
49
  from udata.i18n import gettext as _
50
50
  from udata.models import CommunityResource, Dataset, Follow, Member, db
51
51
  from udata.tags import TAG_MAX_LENGTH, TAG_MIN_LENGTH
52
- from udata.tests.features.territories import create_geozones_fixtures
53
- from udata.tests.helpers import assert200, assert404
52
+ from udata.tests.helpers import assert200, assert404, create_geozones_fixtures
54
53
  from udata.utils import faker, unique_string
55
54
 
56
55
  from . import APITestCase, PytestOnlyAPITestCase
@@ -725,6 +724,19 @@ class DatasetAPITest(APITestCase):
725
724
  dataset = Dataset.objects.first()
726
725
  self.assertEqual(dataset.spatial.geom, SAMPLE_GEOM)
727
726
 
727
+ def test_dataset_api_create_with_invalid_geom_coordinates(self):
728
+ """It should return 400 with invalid GeoJSON coordinates, not 500"""
729
+ self.login()
730
+ data = DatasetFactory.as_dict()
731
+ # Invalid GeoJSON: {} in coordinates instead of numbers (Sentry issue)
732
+ data["spatial"] = {"geom": {"type": "Point", "coordinates": {}}}
733
+ response = self.post(url_for("api.datasets"), data)
734
+ self.assert400(response)
735
+ self.assertEqual(Dataset.objects.count(), 0)
736
+ # Verify error is properly captured in form validation errors
737
+ self.assertIn("errors", response.json)
738
+ self.assertIn("spatial", response.json["errors"])
739
+
728
740
  def test_dataset_api_create_with_legacy_frequency(self):
729
741
  """It should create a dataset from the API with a legacy frequency"""
730
742
  self.login()
@@ -1835,6 +1847,18 @@ class DatasetResourceAPITest(APITestCase):
1835
1847
  f"Resource ids must match existing ones in dataset, ie: {set(str(r.id) for r in self.dataset.resources)}",
1836
1848
  )
1837
1849
 
1850
+ def test_invalid_reorder_dict_without_id(self):
1851
+ """It should return 400 when dict in resources list has no 'id' key"""
1852
+ self.dataset.resources = ResourceFactory.build_batch(3)
1853
+ self.dataset.save()
1854
+
1855
+ # Dict without 'id' key should fail gracefully, not raise KeyError
1856
+ wrong_order_dict_without_id = [{"title": "foo"}, {"title": "bar"}, {"title": "baz"}]
1857
+ response = self.put(
1858
+ url_for("api.resources", dataset=self.dataset), wrong_order_dict_without_id
1859
+ )
1860
+ self.assertStatus(response, 400)
1861
+
1838
1862
  def test_update_local(self):
1839
1863
  resource = ResourceFactory()
1840
1864
  self.dataset.resources.append(resource)
@@ -2507,13 +2531,13 @@ class ResourcesTypesAPITest(APITestCase):
2507
2531
 
2508
2532
 
2509
2533
  class DatasetSchemasAPITest(PytestOnlyAPITestCase):
2510
- def test_dataset_schemas_api_list(self, api, rmock, app):
2534
+ def test_dataset_schemas_api_list(self, rmock, app):
2511
2535
  # Can't use @pytest.mark.options otherwise a request will be
2512
2536
  # made before setting up rmock at module load, resulting in a 404
2513
2537
  app.config["SCHEMA_CATALOG_URL"] = "https://example.com/schemas"
2514
2538
 
2515
2539
  rmock.get("https://example.com/schemas", json=ResourceSchemaMockData.get_mock_data())
2516
- response = api.get(url_for("api.schemas"))
2540
+ response = self.get(url_for("api.schemas"))
2517
2541
 
2518
2542
  assert200(response)
2519
2543
  assert (
@@ -2521,27 +2545,27 @@ class DatasetSchemasAPITest(PytestOnlyAPITestCase):
2521
2545
  )
2522
2546
 
2523
2547
  @pytest.mark.options(SCHEMA_CATALOG_URL=None)
2524
- def test_dataset_schemas_api_list_no_catalog_url(self, api):
2525
- response = api.get(url_for("api.schemas"))
2548
+ def test_dataset_schemas_api_list_no_catalog_url(self):
2549
+ response = self.get(url_for("api.schemas"))
2526
2550
 
2527
2551
  assert200(response)
2528
2552
  assert response.json == []
2529
2553
 
2530
2554
  @pytest.mark.options(SCHEMA_CATALOG_URL="https://example.com/notfound")
2531
- def test_dataset_schemas_api_list_not_found(self, api, rmock):
2555
+ def test_dataset_schemas_api_list_not_found(self, rmock):
2532
2556
  rmock.get("https://example.com/notfound", status_code=404)
2533
- response = api.get(url_for("api.schemas"))
2557
+ response = self.get(url_for("api.schemas"))
2534
2558
  assert404(response)
2535
2559
 
2536
2560
  @pytest.mark.options(SCHEMA_CATALOG_URL="https://example.com/schemas")
2537
- def test_dataset_schemas_api_list_error_no_cache(self, api, rmock):
2561
+ def test_dataset_schemas_api_list_error_no_cache(self, rmock):
2538
2562
  rmock.get("https://example.com/schemas", status_code=500)
2539
2563
 
2540
- response = api.get(url_for("api.schemas"))
2564
+ response = self.get(url_for("api.schemas"))
2541
2565
  assert response.status_code == 503
2542
2566
 
2543
2567
  @pytest.mark.options(SCHEMA_CATALOG_URL="https://example.com/schemas")
2544
- def test_dataset_schemas_api_list_error_w_cache(self, api, rmock, mocker):
2568
+ def test_dataset_schemas_api_list_error_w_cache(self, rmock, mocker):
2545
2569
  cache_mock_set = mocker.patch.object(cache, "set")
2546
2570
  mocker.patch.object(
2547
2571
  cache, "get", return_value=ResourceSchemaMockData.get_mock_data()["schemas"]
@@ -2549,7 +2573,7 @@ class DatasetSchemasAPITest(PytestOnlyAPITestCase):
2549
2573
 
2550
2574
  # Fill cache
2551
2575
  rmock.get("https://example.com/schemas", json=ResourceSchemaMockData.get_mock_data())
2552
- response = api.get(url_for("api.schemas"))
2576
+ response = self.get(url_for("api.schemas"))
2553
2577
  assert200(response)
2554
2578
  assert (
2555
2579
  response.json == ResourceSchemaMockData.get_expected_assignable_schemas_from_mock_data()
@@ -2560,7 +2584,7 @@ class DatasetSchemasAPITest(PytestOnlyAPITestCase):
2560
2584
  rmock.get("https://example.com/schemas", status_code=500)
2561
2585
 
2562
2586
  # Long term cache is used
2563
- response = api.get(url_for("api.schemas"))
2587
+ response = self.get(url_for("api.schemas"))
2564
2588
  assert200(response)
2565
2589
  assert (
2566
2590
  response.json == ResourceSchemaMockData.get_expected_assignable_schemas_from_mock_data()
@@ -2568,7 +2592,7 @@ class DatasetSchemasAPITest(PytestOnlyAPITestCase):
2568
2592
 
2569
2593
 
2570
2594
  class HarvestMetadataAPITest(PytestOnlyAPITestCase):
2571
- def test_dataset_with_harvest_metadata(self, api):
2595
+ def test_dataset_with_harvest_metadata(self):
2572
2596
  date = datetime(2022, 2, 22, tzinfo=pytz.UTC)
2573
2597
  harvest_metadata = HarvestDatasetMetadata(
2574
2598
  backend="DCAT",
@@ -2586,7 +2610,7 @@ class HarvestMetadataAPITest(PytestOnlyAPITestCase):
2586
2610
  )
2587
2611
  dataset = DatasetFactory(harvest=harvest_metadata)
2588
2612
 
2589
- response = api.get(url_for("api.dataset", dataset=dataset))
2613
+ response = self.get(url_for("api.dataset", dataset=dataset))
2590
2614
  assert200(response)
2591
2615
  assert response.json["harvest"] == {
2592
2616
  "backend": "DCAT",
@@ -2603,7 +2627,7 @@ class HarvestMetadataAPITest(PytestOnlyAPITestCase):
2603
2627
  "archived": "not-on-remote",
2604
2628
  }
2605
2629
 
2606
- def test_dataset_with_resource_harvest_metadata(self, api):
2630
+ def test_dataset_with_resource_harvest_metadata(self):
2607
2631
  date = datetime(2022, 2, 22, tzinfo=pytz.UTC)
2608
2632
 
2609
2633
  harvest_metadata = HarvestResourceMetadata(
@@ -2613,7 +2637,7 @@ class HarvestMetadataAPITest(PytestOnlyAPITestCase):
2613
2637
  )
2614
2638
  dataset = DatasetFactory(resources=[ResourceFactory(harvest=harvest_metadata)])
2615
2639
 
2616
- response = api.get(url_for("api.dataset", dataset=dataset))
2640
+ response = self.get(url_for("api.dataset", dataset=dataset))
2617
2641
  assert200(response)
2618
2642
  assert response.json["resources"][0]["harvest"] == {
2619
2643
  "issued_at": date.isoformat(),
@@ -2621,7 +2645,7 @@ class HarvestMetadataAPITest(PytestOnlyAPITestCase):
2621
2645
  "uri": "http://domain.gouv.fr/dataset/uri",
2622
2646
  }
2623
2647
 
2624
- def test_dataset_with_harvest_computed_dates(self, api):
2648
+ def test_dataset_with_harvest_computed_dates(self):
2625
2649
  # issued_date takes precedence over internal creation date and harvest created_at on dataset
2626
2650
  issued_date = datetime(2022, 2, 22, tzinfo=pytz.UTC)
2627
2651
  creation_date = datetime(2022, 2, 23, tzinfo=pytz.UTC)
@@ -2632,7 +2656,7 @@ class HarvestMetadataAPITest(PytestOnlyAPITestCase):
2632
2656
  modified_at=modification_date,
2633
2657
  )
2634
2658
  dataset = DatasetFactory(harvest=harvest_metadata)
2635
- response = api.get(url_for("api.dataset", dataset=dataset))
2659
+ response = self.get(url_for("api.dataset", dataset=dataset))
2636
2660
  assert200(response)
2637
2661
  assert response.json["created_at"] == issued_date.isoformat()
2638
2662
  assert response.json["last_modified"] == modification_date.isoformat()
@@ -2644,7 +2668,7 @@ class HarvestMetadataAPITest(PytestOnlyAPITestCase):
2644
2668
  modified_at=modification_date,
2645
2669
  )
2646
2670
  dataset = DatasetFactory(harvest=harvest_metadata)
2647
- response = api.get(url_for("api.dataset", dataset=dataset))
2671
+ response = self.get(url_for("api.dataset", dataset=dataset))
2648
2672
  assert200(response)
2649
2673
  assert response.json["created_at"] == creation_date.isoformat()
2650
2674
  assert response.json["last_modified"] == modification_date.isoformat()
@@ -2655,7 +2679,7 @@ class HarvestMetadataAPITest(PytestOnlyAPITestCase):
2655
2679
  modified_at=modification_date,
2656
2680
  )
2657
2681
  dataset = DatasetFactory(resources=[ResourceFactory(harvest=resource_harvest_metadata)])
2658
- response = api.get(url_for("api.dataset", dataset=dataset))
2682
+ response = self.get(url_for("api.dataset", dataset=dataset))
2659
2683
  assert200(response)
2660
2684
  assert response.json["resources"][0]["created_at"] == issued_date.isoformat()
2661
2685
  assert response.json["resources"][0]["last_modified"] == modification_date.isoformat()