udata 12.0.2.dev17__py3-none-any.whl → 12.0.2.dev19__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 (115) hide show
  1. udata/commands/tests/test_fixtures.py +2 -3
  2. udata/core/badges/tests/test_commands.py +2 -4
  3. udata/core/badges/tests/test_model.py +2 -2
  4. udata/core/dataservices/models.py +4 -0
  5. udata/core/dataservices/search.py +1 -1
  6. udata/core/dataset/search.py +2 -2
  7. udata/core/organization/search.py +1 -1
  8. udata/core/pages/tests/test_api.py +0 -2
  9. udata/core/reuse/search.py +1 -1
  10. udata/core/spatial/tests/test_api.py +17 -20
  11. udata/core/spatial/tests/test_models.py +3 -3
  12. udata/core/user/tests/test_user_model.py +2 -6
  13. udata/features/identicon/tests/test_backends.py +3 -13
  14. udata/harvest/tests/ckan/test_ckan_backend.py +300 -337
  15. udata/harvest/tests/ckan/test_ckan_backend_errors.py +94 -99
  16. udata/harvest/tests/ckan/test_ckan_backend_filters.py +128 -122
  17. udata/harvest/tests/ckan/test_dkan_backend.py +39 -51
  18. udata/harvest/tests/test_actions.py +7 -7
  19. udata/harvest/tests/test_api.py +2 -4
  20. udata/harvest/tests/test_base_backend.py +3 -4
  21. udata/harvest/tests/test_dcat_backend.py +4 -6
  22. udata/harvest/tests/test_models.py +2 -4
  23. udata/harvest/tests/test_notifications.py +2 -4
  24. udata/harvest/tests/test_tasks.py +2 -3
  25. udata/tests/__init__.py +40 -58
  26. udata/tests/api/__init__.py +87 -2
  27. udata/tests/api/test_activities_api.py +17 -23
  28. udata/tests/api/test_auth_api.py +2 -4
  29. udata/tests/api/test_contact_points.py +48 -54
  30. udata/tests/api/test_dataservices_api.py +0 -2
  31. udata/tests/api/test_datasets_api.py +15 -29
  32. udata/tests/api/test_me_api.py +4 -6
  33. udata/tests/api/test_organizations_api.py +19 -38
  34. udata/tests/api/test_reports_api.py +0 -4
  35. udata/tests/api/test_reuses_api.py +9 -19
  36. udata/tests/api/test_swagger.py +2 -3
  37. udata/tests/api/test_tags_api.py +6 -7
  38. udata/tests/api/test_transfer_api.py +0 -2
  39. udata/tests/api/test_user_api.py +8 -10
  40. udata/tests/apiv2/test_datasets.py +0 -4
  41. udata/tests/apiv2/test_me_api.py +0 -2
  42. udata/tests/apiv2/test_organizations.py +0 -2
  43. udata/tests/apiv2/test_swagger.py +2 -3
  44. udata/tests/apiv2/test_topics.py +0 -2
  45. udata/tests/cli/test_cli_base.py +14 -12
  46. udata/tests/cli/test_db_cli.py +51 -54
  47. udata/tests/contact_point/test_contact_point_models.py +2 -2
  48. udata/tests/dataservice/test_csv_adapter.py +2 -5
  49. udata/tests/dataservice/test_dataservice_rdf.py +3 -6
  50. udata/tests/dataservice/test_dataservice_tasks.py +36 -38
  51. udata/tests/dataset/test_csv_adapter.py +2 -5
  52. udata/tests/dataset/test_dataset_actions.py +2 -4
  53. udata/tests/dataset/test_dataset_commands.py +2 -4
  54. udata/tests/dataset/test_dataset_events.py +3 -3
  55. udata/tests/dataset/test_dataset_model.py +6 -7
  56. udata/tests/dataset/test_dataset_rdf.py +6 -9
  57. udata/tests/dataset/test_dataset_recommendations.py +2 -2
  58. udata/tests/dataset/test_dataset_tasks.py +66 -68
  59. udata/tests/dataset/test_resource_preview.py +39 -48
  60. udata/tests/dataset/test_transport_tasks.py +2 -2
  61. udata/tests/features/territories/__init__.py +0 -6
  62. udata/tests/features/territories/test_territories_api.py +25 -24
  63. udata/tests/forms/test_current_user_field.py +2 -2
  64. udata/tests/forms/test_dict_field.py +2 -4
  65. udata/tests/forms/test_extras_fields.py +2 -3
  66. udata/tests/forms/test_image_field.py +2 -2
  67. udata/tests/forms/test_model_field.py +2 -4
  68. udata/tests/forms/test_publish_as_field.py +2 -4
  69. udata/tests/forms/test_user_forms.py +26 -29
  70. udata/tests/frontend/test_auth.py +2 -3
  71. udata/tests/frontend/test_csv.py +5 -6
  72. udata/tests/frontend/test_error_handlers.py +2 -3
  73. udata/tests/frontend/test_hooks.py +5 -7
  74. udata/tests/frontend/test_markdown.py +3 -4
  75. udata/tests/helpers.py +2 -7
  76. udata/tests/metrics/test_metrics.py +52 -48
  77. udata/tests/metrics/test_tasks.py +154 -150
  78. udata/tests/organization/test_csv_adapter.py +2 -5
  79. udata/tests/organization/test_notifications.py +2 -4
  80. udata/tests/organization/test_organization_model.py +3 -4
  81. udata/tests/organization/test_organization_rdf.py +2 -8
  82. udata/tests/plugin.py +6 -110
  83. udata/tests/reuse/test_reuse_model.py +3 -4
  84. udata/tests/site/test_site_api.py +0 -2
  85. udata/tests/site/test_site_csv_exports.py +0 -2
  86. udata/tests/site/test_site_metrics.py +2 -4
  87. udata/tests/site/test_site_model.py +2 -2
  88. udata/tests/site/test_site_rdf.py +3 -6
  89. udata/tests/test_activity.py +3 -3
  90. udata/tests/test_api_fields.py +6 -9
  91. udata/tests/test_cors.py +0 -2
  92. udata/tests/test_dcat_commands.py +2 -3
  93. udata/tests/test_discussions.py +2 -7
  94. udata/tests/test_mail.py +4 -10
  95. udata/tests/test_migrations.py +413 -419
  96. udata/tests/test_model.py +10 -11
  97. udata/tests/test_notifications.py +2 -3
  98. udata/tests/test_owned.py +3 -3
  99. udata/tests/test_routing.py +5 -5
  100. udata/tests/test_storages.py +6 -5
  101. udata/tests/test_tags.py +2 -1
  102. udata/tests/test_topics.py +2 -4
  103. udata/tests/test_transfer.py +4 -5
  104. udata/tests/topic/test_topic_tasks.py +25 -27
  105. udata/tests/user/test_user_rdf.py +2 -8
  106. udata/tests/workers/test_jobs_commands.py +2 -2
  107. udata/tests/workers/test_tasks_routing.py +27 -27
  108. {udata-12.0.2.dev17.dist-info → udata-12.0.2.dev19.dist-info}/METADATA +1 -1
  109. {udata-12.0.2.dev17.dist-info → udata-12.0.2.dev19.dist-info}/RECORD +113 -115
  110. udata/tests/frontend/__init__.py +0 -23
  111. udata/tests/metrics/conftest.py +0 -15
  112. {udata-12.0.2.dev17.dist-info → udata-12.0.2.dev19.dist-info}/WHEEL +0 -0
  113. {udata-12.0.2.dev17.dist-info → udata-12.0.2.dev19.dist-info}/entry_points.txt +0 -0
  114. {udata-12.0.2.dev17.dist-info → udata-12.0.2.dev19.dist-info}/licenses/LICENSE +0 -0
  115. {udata-12.0.2.dev17.dist-info → udata-12.0.2.dev19.dist-info}/top_level.txt +0 -0
@@ -2,11 +2,7 @@ import pytest
2
2
 
3
3
  from udata.harvest import actions
4
4
  from udata.harvest.tests.factories import HarvestSourceFactory
5
-
6
- pytestmark = [
7
- pytest.mark.usefixtures("clean_db"),
8
- pytest.mark.options(PLUGINS=["ckan"]),
9
- ]
5
+ from udata.tests.api import PytestOnlyDBTestCase
10
6
 
11
7
  CKAN_URL = "https://harvest.me/"
12
8
  API_URL = "{}api/3/action/package_list".format(CKAN_URL)
@@ -17,124 +13,123 @@ API_URL = "{}api/3/action/package_list".format(CKAN_URL)
17
13
  STATUS_CODE = (400, 500)
18
14
 
19
15
 
20
- @pytest.mark.parametrize("code", STATUS_CODE)
21
- def test_html_error(rmock, code):
22
- # Happens with wrong source URL (html is returned instead of json)
23
- html = "<html><body>Error</body></html>"
24
- source = HarvestSourceFactory(backend="ckan", url=CKAN_URL)
25
-
26
- rmock.get(API_URL, text=html, status_code=code, headers={"Content-Type": "text/html"})
27
-
28
- actions.run(source)
29
-
30
- source.reload()
31
-
32
- job = source.get_last_job()
33
- assert len(job.items) == 0
34
- assert len(job.errors) == 1
35
- error = job.errors[0]
36
- # HTML is detected and does not clutter the message
37
- assert html not in error.message
38
-
39
-
40
- @pytest.mark.parametrize("code", STATUS_CODE)
41
- def test_plain_text_error(rmock, code):
42
- source = HarvestSourceFactory(backend="ckan", url=CKAN_URL)
43
-
44
- rmock.get(
45
- API_URL, text='"Some error"', status_code=code, headers={"Content-Type": "text/plain"}
46
- )
16
+ @pytest.mark.options(PLUGINS=["ckan"])
17
+ class CkanBackendErrorsTest(PytestOnlyDBTestCase):
18
+ @pytest.mark.parametrize("code", STATUS_CODE)
19
+ def test_html_error(self, rmock, code):
20
+ # Happens with wrong source URL (html is returned instead of json)
21
+ html = "<html><body>Error</body></html>"
22
+ source = HarvestSourceFactory(backend="ckan", url=CKAN_URL)
47
23
 
48
- actions.run(source)
24
+ rmock.get(API_URL, text=html, status_code=code, headers={"Content-Type": "text/html"})
49
25
 
50
- source.reload()
26
+ actions.run(source)
51
27
 
52
- job = source.get_last_job()
53
- assert len(job.items) == 0
54
- assert len(job.errors) == 1
55
- error = job.errors[0]
56
- # Raw quoted string is properly unquoted
57
- http_message = "Server Error" if code == 500 else "Client Error"
58
- assert (
59
- error.message
60
- == f"{code} {http_message}: None for url: https://harvest.me/api/3/action/package_list"
61
- )
28
+ source.reload()
62
29
 
30
+ job = source.get_last_job()
31
+ assert len(job.items) == 0
32
+ assert len(job.errors) == 1
33
+ error = job.errors[0]
34
+ # HTML is detected and does not clutter the message
35
+ assert html not in error.message
63
36
 
64
- def test_200_plain_text_error(rmock):
65
- source = HarvestSourceFactory(backend="ckan", url=CKAN_URL)
37
+ @pytest.mark.parametrize("code", STATUS_CODE)
38
+ def test_plain_text_error(self, rmock, code):
39
+ source = HarvestSourceFactory(backend="ckan", url=CKAN_URL)
66
40
 
67
- rmock.get(API_URL, text='"Some error"', status_code=200, headers={"Content-Type": "text/plain"})
41
+ rmock.get(
42
+ API_URL, text='"Some error"', status_code=code, headers={"Content-Type": "text/plain"}
43
+ )
68
44
 
69
- actions.run(source)
45
+ actions.run(source)
70
46
 
71
- source.reload()
47
+ source.reload()
72
48
 
73
- job = source.get_last_job()
74
- assert len(job.items) == 0
75
- assert len(job.errors) == 1
76
- error = job.errors[0]
77
- # Raw quoted string is properly unquoted
78
- assert error.message == "Some error"
49
+ job = source.get_last_job()
50
+ assert len(job.items) == 0
51
+ assert len(job.errors) == 1
52
+ error = job.errors[0]
53
+ # Raw quoted string is properly unquoted
54
+ http_message = "Server Error" if code == 500 else "Client Error"
55
+ assert (
56
+ error.message
57
+ == f"{code} {http_message}: None for url: https://harvest.me/api/3/action/package_list"
58
+ )
79
59
 
60
+ def test_200_plain_text_error(self, rmock):
61
+ source = HarvestSourceFactory(backend="ckan", url=CKAN_URL)
80
62
 
81
- def test_standard_api_json_error(rmock):
82
- json = {"success": False, "error": "an error"}
83
- source = HarvestSourceFactory(backend="ckan", url=CKAN_URL)
63
+ rmock.get(
64
+ API_URL, text='"Some error"', status_code=200, headers={"Content-Type": "text/plain"}
65
+ )
84
66
 
85
- rmock.get(API_URL, json=json, status_code=200, headers={"Content-Type": "application/json"})
67
+ actions.run(source)
86
68
 
87
- actions.run(source)
69
+ source.reload()
88
70
 
89
- source.reload()
71
+ job = source.get_last_job()
72
+ assert len(job.items) == 0
73
+ assert len(job.errors) == 1
74
+ error = job.errors[0]
75
+ # Raw quoted string is properly unquoted
76
+ assert error.message == "Some error"
90
77
 
91
- job = source.get_last_job()
92
- assert len(job.items) == 0
93
- assert len(job.errors) == 1
94
- error = job.errors[0]
95
- assert error.message == "an error"
78
+ def test_standard_api_json_error(self, rmock):
79
+ json = {"success": False, "error": "an error"}
80
+ source = HarvestSourceFactory(backend="ckan", url=CKAN_URL)
96
81
 
82
+ rmock.get(API_URL, json=json, status_code=200, headers={"Content-Type": "application/json"})
97
83
 
98
- def test_standard_api_json_error_with_details(rmock):
99
- json = {
100
- "success": False,
101
- "error": {
102
- "message": "an error",
103
- },
104
- }
105
- source = HarvestSourceFactory(backend="ckan", url=CKAN_URL)
84
+ actions.run(source)
106
85
 
107
- rmock.get(API_URL, json=json, status_code=200, headers={"Content-Type": "application/json"})
86
+ source.reload()
108
87
 
109
- actions.run(source)
88
+ job = source.get_last_job()
89
+ assert len(job.items) == 0
90
+ assert len(job.errors) == 1
91
+ error = job.errors[0]
92
+ assert error.message == "an error"
110
93
 
111
- source.reload()
94
+ def test_standard_api_json_error_with_details(self, rmock):
95
+ json = {
96
+ "success": False,
97
+ "error": {
98
+ "message": "an error",
99
+ },
100
+ }
101
+ source = HarvestSourceFactory(backend="ckan", url=CKAN_URL)
112
102
 
113
- job = source.get_last_job()
114
- assert len(job.items) == 0
115
- assert len(job.errors) == 1
116
- error = job.errors[0]
117
- assert error.message == "an error"
103
+ rmock.get(API_URL, json=json, status_code=200, headers={"Content-Type": "application/json"})
118
104
 
105
+ actions.run(source)
119
106
 
120
- def test_standard_api_json_error_with_details_and_type(rmock):
121
- json = {
122
- "success": False,
123
- "error": {
124
- "message": "Access denied",
125
- "__type": "Authorization Error",
126
- },
127
- }
128
- source = HarvestSourceFactory(backend="ckan", url=CKAN_URL)
107
+ source.reload()
129
108
 
130
- rmock.get(API_URL, json=json, status_code=200, headers={"Content-Type": "application/json"})
109
+ job = source.get_last_job()
110
+ assert len(job.items) == 0
111
+ assert len(job.errors) == 1
112
+ error = job.errors[0]
113
+ assert error.message == "an error"
131
114
 
132
- actions.run(source)
115
+ def test_standard_api_json_error_with_details_and_type(self, rmock):
116
+ json = {
117
+ "success": False,
118
+ "error": {
119
+ "message": "Access denied",
120
+ "__type": "Authorization Error",
121
+ },
122
+ }
123
+ source = HarvestSourceFactory(backend="ckan", url=CKAN_URL)
133
124
 
134
- source.reload()
125
+ rmock.get(API_URL, json=json, status_code=200, headers={"Content-Type": "application/json"})
135
126
 
136
- job = source.get_last_job()
137
- assert len(job.items) == 0
138
- assert len(job.errors) == 1
139
- error = job.errors[0]
140
- assert error.message == "Authorization Error: Access denied"
127
+ actions.run(source)
128
+
129
+ source.reload()
130
+
131
+ job = source.get_last_job()
132
+ assert len(job.items) == 0
133
+ assert len(job.errors) == 1
134
+ error = job.errors[0]
135
+ assert error.message == "Authorization Error: Access denied"
@@ -4,127 +4,133 @@ import pytest
4
4
 
5
5
  from udata.harvest import actions
6
6
  from udata.harvest.tests.factories import HarvestSourceFactory
7
+ from udata.tests.api import PytestOnlyDBTestCase
7
8
  from udata.utils import faker
8
9
 
9
- pytestmark = [
10
- pytest.mark.usefixtures("clean_db"),
11
- pytest.mark.options(PLUGINS=["ckan"]),
12
- ]
13
-
14
-
15
- def test_include_org_filter(ckan, rmock):
16
- source = HarvestSourceFactory(
17
- backend="ckan",
18
- url=ckan.BASE_URL,
19
- config={"filters": [{"key": "organization", "value": "organization_name"}]},
20
- )
21
-
22
- rmock.get(
23
- ckan.PACKAGE_SEARCH_URL,
24
- json={"success": True, "result": {"results": []}},
25
- status_code=200,
26
- headers={"Content-Type": "application/json"},
27
- )
28
-
29
- actions.run(source)
30
- source.reload()
31
-
32
- assert rmock.call_count == 1
33
- params = {"q": "organization:organization_name", "rows": 1000}
34
- assert rmock.last_request.url == f"{ckan.PACKAGE_SEARCH_URL}?{urllib.parse.urlencode(params)}"
35
-
36
-
37
- def test_exclude_org_filter(ckan, rmock):
38
- source = HarvestSourceFactory(
39
- backend="ckan",
40
- url=ckan.BASE_URL,
41
- config={
42
- "filters": [{"key": "organization", "value": "organization_name", "type": "exclude"}]
43
- },
44
- )
45
-
46
- rmock.get(
47
- ckan.PACKAGE_SEARCH_URL,
48
- json={"success": True, "result": {"results": []}},
49
- status_code=200,
50
- headers={"Content-Type": "application/json"},
51
- )
52
-
53
- actions.run(source)
54
- source.reload()
55
-
56
- assert rmock.call_count == 1
57
-
58
- params = {"q": "-organization:organization_name", "rows": 1000}
59
- assert rmock.last_request.url == f"{ckan.PACKAGE_SEARCH_URL}?{urllib.parse.urlencode(params)}"
60
-
61
-
62
- def test_tag_filter(ckan, rmock):
63
- tag = faker.word()
64
- source = HarvestSourceFactory(
65
- backend="ckan", url=ckan.BASE_URL, config={"filters": [{"key": "tags", "value": tag}]}
66
- )
67
-
68
- rmock.get(
69
- ckan.PACKAGE_SEARCH_URL,
70
- json={"success": True, "result": {"results": []}},
71
- status_code=200,
72
- headers={"Content-Type": "application/json"},
73
- )
74
-
75
- actions.run(source)
76
- source.reload()
77
-
78
- assert rmock.call_count == 1
79
- params = {"q": f"tags:{tag}", "rows": 1000}
80
- assert rmock.last_request.url == f"{ckan.PACKAGE_SEARCH_URL}?{urllib.parse.urlencode(params)}"
81
-
82
-
83
- def test_exclude_tag_filter(ckan, rmock):
84
- tag = faker.word()
85
- source = HarvestSourceFactory(
86
- backend="ckan",
87
- url=ckan.BASE_URL,
88
- config={"filters": [{"key": "tags", "value": tag, "type": "exclude"}]},
89
- )
90
-
91
- rmock.get(
92
- ckan.PACKAGE_SEARCH_URL,
93
- json={"success": True, "result": {"results": []}},
94
- status_code=200,
95
- headers={"Content-Type": "application/json"},
96
- )
97
-
98
- actions.run(source)
99
- source.reload()
100
-
101
- assert rmock.call_count == 1
102
- params = {"q": f"-tags:{tag}", "rows": 1000}
103
- assert rmock.last_request.url == f"{ckan.PACKAGE_SEARCH_URL}?{urllib.parse.urlencode(params)}"
104
-
105
-
106
- def test_can_have_multiple_filters(ckan, rmock):
107
- source = HarvestSourceFactory(
108
- backend="ckan",
109
- url=ckan.BASE_URL,
110
- config={
111
- "filters": [
112
- {"key": "organization", "value": "organization_name"},
113
- {"key": "tags", "value": "tag-2", "type": "exclude"},
114
- ]
115
- },
116
- )
117
-
118
- rmock.get(
119
- ckan.PACKAGE_SEARCH_URL,
120
- json={"success": True, "result": {"results": []}},
121
- status_code=200,
122
- headers={"Content-Type": "application/json"},
123
- )
124
-
125
- actions.run(source)
126
- source.reload()
127
-
128
- assert rmock.call_count == 1
129
- params = {"q": "organization:organization_name AND -tags:tag-2", "rows": 1000}
130
- assert rmock.last_request.url == f"{ckan.PACKAGE_SEARCH_URL}?{urllib.parse.urlencode(params)}"
10
+
11
+ @pytest.mark.options(PLUGINS=["ckan"])
12
+ class CkanBackendFilterTest(PytestOnlyDBTestCase):
13
+ def test_include_org_filter(self, ckan, rmock):
14
+ source = HarvestSourceFactory(
15
+ backend="ckan",
16
+ url=ckan.BASE_URL,
17
+ config={"filters": [{"key": "organization", "value": "organization_name"}]},
18
+ )
19
+
20
+ rmock.get(
21
+ ckan.PACKAGE_SEARCH_URL,
22
+ json={"success": True, "result": {"results": []}},
23
+ status_code=200,
24
+ headers={"Content-Type": "application/json"},
25
+ )
26
+
27
+ actions.run(source)
28
+ source.reload()
29
+
30
+ assert rmock.call_count == 1
31
+ params = {"q": "organization:organization_name", "rows": 1000}
32
+ assert (
33
+ rmock.last_request.url == f"{ckan.PACKAGE_SEARCH_URL}?{urllib.parse.urlencode(params)}"
34
+ )
35
+
36
+ def test_exclude_org_filter(self, ckan, rmock):
37
+ source = HarvestSourceFactory(
38
+ backend="ckan",
39
+ url=ckan.BASE_URL,
40
+ config={
41
+ "filters": [
42
+ {"key": "organization", "value": "organization_name", "type": "exclude"}
43
+ ]
44
+ },
45
+ )
46
+
47
+ rmock.get(
48
+ ckan.PACKAGE_SEARCH_URL,
49
+ json={"success": True, "result": {"results": []}},
50
+ status_code=200,
51
+ headers={"Content-Type": "application/json"},
52
+ )
53
+
54
+ actions.run(source)
55
+ source.reload()
56
+
57
+ assert rmock.call_count == 1
58
+
59
+ params = {"q": "-organization:organization_name", "rows": 1000}
60
+ assert (
61
+ rmock.last_request.url == f"{ckan.PACKAGE_SEARCH_URL}?{urllib.parse.urlencode(params)}"
62
+ )
63
+
64
+ def test_tag_filter(self, ckan, rmock):
65
+ tag = faker.word()
66
+ source = HarvestSourceFactory(
67
+ backend="ckan", url=ckan.BASE_URL, config={"filters": [{"key": "tags", "value": tag}]}
68
+ )
69
+
70
+ rmock.get(
71
+ ckan.PACKAGE_SEARCH_URL,
72
+ json={"success": True, "result": {"results": []}},
73
+ status_code=200,
74
+ headers={"Content-Type": "application/json"},
75
+ )
76
+
77
+ actions.run(source)
78
+ source.reload()
79
+
80
+ assert rmock.call_count == 1
81
+ params = {"q": f"tags:{tag}", "rows": 1000}
82
+ assert (
83
+ rmock.last_request.url == f"{ckan.PACKAGE_SEARCH_URL}?{urllib.parse.urlencode(params)}"
84
+ )
85
+
86
+ def test_exclude_tag_filter(self, ckan, rmock):
87
+ tag = faker.word()
88
+ source = HarvestSourceFactory(
89
+ backend="ckan",
90
+ url=ckan.BASE_URL,
91
+ config={"filters": [{"key": "tags", "value": tag, "type": "exclude"}]},
92
+ )
93
+
94
+ rmock.get(
95
+ ckan.PACKAGE_SEARCH_URL,
96
+ json={"success": True, "result": {"results": []}},
97
+ status_code=200,
98
+ headers={"Content-Type": "application/json"},
99
+ )
100
+
101
+ actions.run(source)
102
+ source.reload()
103
+
104
+ assert rmock.call_count == 1
105
+ params = {"q": f"-tags:{tag}", "rows": 1000}
106
+ assert (
107
+ rmock.last_request.url == f"{ckan.PACKAGE_SEARCH_URL}?{urllib.parse.urlencode(params)}"
108
+ )
109
+
110
+ def test_can_have_multiple_filters(self, ckan, rmock):
111
+ source = HarvestSourceFactory(
112
+ backend="ckan",
113
+ url=ckan.BASE_URL,
114
+ config={
115
+ "filters": [
116
+ {"key": "organization", "value": "organization_name"},
117
+ {"key": "tags", "value": "tag-2", "type": "exclude"},
118
+ ]
119
+ },
120
+ )
121
+
122
+ rmock.get(
123
+ ckan.PACKAGE_SEARCH_URL,
124
+ json={"success": True, "result": {"results": []}},
125
+ status_code=200,
126
+ headers={"Content-Type": "application/json"},
127
+ )
128
+
129
+ actions.run(source)
130
+ source.reload()
131
+
132
+ assert rmock.call_count == 1
133
+ params = {"q": "organization:organization_name AND -tags:tag-2", "rows": 1000}
134
+ assert (
135
+ rmock.last_request.url == f"{ckan.PACKAGE_SEARCH_URL}?{urllib.parse.urlencode(params)}"
136
+ )
@@ -4,13 +4,11 @@ from datetime import datetime
4
4
 
5
5
  import pytest
6
6
 
7
- from udata.app import create_app
8
7
  from udata.core.organization.factories import OrganizationFactory
9
8
  from udata.harvest import actions
10
9
  from udata.harvest.tests.factories import HarvestSourceFactory
11
10
  from udata.models import Dataset
12
- from udata.settings import Defaults, Testing
13
- from udata.tests.plugin import drop_db
11
+ from udata.tests.api import PytestOnlyDBTestCase
14
12
 
15
13
 
16
14
  def data_path(filename):
@@ -18,51 +16,41 @@ def data_path(filename):
18
16
  return os.path.join(os.path.dirname(__file__), "data", filename)
19
17
 
20
18
 
21
- class DkanSettings(Testing):
22
- PLUGINS = ["dkan"]
23
-
24
-
25
- @pytest.fixture(scope="module")
26
- def app(request):
27
- """Create an udata app once for the module."""
28
- app = create_app(Defaults, override=DkanSettings)
29
- with app.app_context():
30
- drop_db(app)
31
- yield app
32
- with app.app_context():
33
- drop_db(app)
34
-
35
-
36
- def test_dkan_french_w_license(app, rmock):
37
- """CKAN Harvester should accept the minimum dataset payload"""
38
- DKAN_URL = "https://harvest.me/"
39
- API_URL = "{}api/3/action/".format(DKAN_URL)
40
- PACKAGE_LIST_URL = "{}package_list".format(API_URL)
41
- PACKAGE_SHOW_URL = "{}package_show".format(API_URL)
42
-
43
- with open(data_path("dkan-french-w-license.json")) as ifile:
44
- data = json.loads(ifile.read())
45
-
46
- org = OrganizationFactory()
47
- source = HarvestSourceFactory(backend="dkan", url=DKAN_URL, organization=org)
48
- rmock.get(
49
- PACKAGE_LIST_URL,
50
- json={"success": True, "result": ["fake-name"]},
51
- status_code=200,
52
- headers={"Content-Type": "application/json"},
53
- )
54
- rmock.get(
55
- PACKAGE_SHOW_URL, json=data, status_code=200, headers={"Content-Type": "application/json"}
56
- )
57
- actions.run(source)
58
- source.reload()
59
- assert source.get_last_job().status == "done"
60
-
61
- datasets = Dataset.objects.filter(organization=org)
62
- assert len(datasets) > 0
63
-
64
- dataset = datasets.get(**{"harvest__remote_id": "04be6288-696d-4331-850d-a144871a7e3a"})
65
- assert dataset.harvest.created_at == datetime(2019, 12, 10, 0, 0)
66
- assert dataset.harvest.modified_at == datetime(2019, 9, 30, 0, 0)
67
- assert len(dataset.resources) == 2
68
- assert "xlsx" in [r.format for r in dataset.resources]
19
+ @pytest.mark.options(PLUGINS=["dkan"])
20
+ class DkanBackendTest(PytestOnlyDBTestCase):
21
+ def test_dkan_french_w_license(self, rmock):
22
+ """CKAN Harvester should accept the minimum dataset payload"""
23
+ DKAN_URL = "https://harvest.me/"
24
+ API_URL = "{}api/3/action/".format(DKAN_URL)
25
+ PACKAGE_LIST_URL = "{}package_list".format(API_URL)
26
+ PACKAGE_SHOW_URL = "{}package_show".format(API_URL)
27
+
28
+ with open(data_path("dkan-french-w-license.json")) as ifile:
29
+ data = json.loads(ifile.read())
30
+
31
+ org = OrganizationFactory()
32
+ source = HarvestSourceFactory(backend="dkan", url=DKAN_URL, organization=org)
33
+ rmock.get(
34
+ PACKAGE_LIST_URL,
35
+ json={"success": True, "result": ["fake-name"]},
36
+ status_code=200,
37
+ headers={"Content-Type": "application/json"},
38
+ )
39
+ rmock.get(
40
+ PACKAGE_SHOW_URL,
41
+ json=data,
42
+ status_code=200,
43
+ headers={"Content-Type": "application/json"},
44
+ )
45
+ actions.run(source)
46
+ source.reload()
47
+ assert source.get_last_job().status == "done"
48
+
49
+ datasets = Dataset.objects.filter(organization=org)
50
+ assert len(datasets) > 0
51
+
52
+ dataset = datasets.get(**{"harvest__remote_id": "04be6288-696d-4331-850d-a144871a7e3a"})
53
+ assert dataset.harvest.created_at == datetime(2019, 12, 10, 0, 0)
54
+ assert dataset.harvest.modified_at == datetime(2019, 9, 30, 0, 0)
55
+ assert len(dataset.resources) == 2
56
+ assert "xlsx" in [r.format for r in dataset.resources]
@@ -16,6 +16,7 @@ from udata.core.dataset.models import HarvestDatasetMetadata
16
16
  from udata.core.organization.factories import OrganizationFactory
17
17
  from udata.core.user.factories import UserFactory
18
18
  from udata.models import Dataset, PeriodicTask
19
+ from udata.tests.api import PytestOnlyDBTestCase
19
20
  from udata.tests.helpers import assert_emit, assert_equal_dates, assert_not_emit
20
21
  from udata.utils import faker
21
22
 
@@ -40,12 +41,8 @@ from .factories import (
40
41
 
41
42
  log = logging.getLogger(__name__)
42
43
 
43
- pytestmark = [
44
- pytest.mark.usefixtures("clean_db"),
45
- ]
46
44
 
47
-
48
- class HarvestActionsTest:
45
+ class HarvestActionsTest(PytestOnlyDBTestCase):
49
46
  def test_list_backends(self):
50
47
  for backend in actions.list_backends():
51
48
  assert issubclass(backend, BaseBackend)
@@ -453,7 +450,10 @@ class HarvestActionsTest:
453
450
  assert result.errors == 1
454
451
 
455
452
 
456
- class ExecutionTestMixin(MockBackendsMixin):
453
+ class ExecutionTestMixin(MockBackendsMixin, PytestOnlyDBTestCase):
454
+ def action(self, *args, **kwargs):
455
+ raise NotImplementedError
456
+
457
457
  def test_default(self):
458
458
  org = OrganizationFactory()
459
459
  source = HarvestSourceFactory(backend="factory", organization=org)
@@ -610,7 +610,7 @@ class HarvestRunTest(ExecutionTestMixin):
610
610
  return actions.run(*args, **kwargs)
611
611
 
612
612
 
613
- class HarvestPreviewTest(MockBackendsMixin):
613
+ class HarvestPreviewTest(MockBackendsMixin, PytestOnlyDBTestCase):
614
614
  def test_preview(self):
615
615
  org = OrganizationFactory()
616
616
  source = HarvestSourceFactory(backend="factory", organization=org)
@@ -8,6 +8,7 @@ from pytest_mock import MockerFixture
8
8
  from udata.core.organization.factories import OrganizationFactory
9
9
  from udata.core.user.factories import AdminFactory, UserFactory
10
10
  from udata.models import Member, PeriodicTask
11
+ from udata.tests.api import PytestOnlyAPITestCase
11
12
  from udata.tests.helpers import assert200, assert201, assert204, assert400, assert403, assert404
12
13
  from udata.tests.plugin import ApiClient
13
14
  from udata.utils import faker
@@ -25,10 +26,7 @@ from .factories import HarvestSourceFactory, MockBackendsMixin
25
26
  log = logging.getLogger(__name__)
26
27
 
27
28
 
28
- @pytest.mark.usefixtures("clean_db")
29
- class HarvestAPITest(MockBackendsMixin):
30
- modules = []
31
-
29
+ class HarvestAPITest(MockBackendsMixin, PytestOnlyAPITestCase):
32
30
  def test_list_backends(self, api):
33
31
  """It should fetch the harvest backends list from the API"""
34
32
  response = api.get(url_for("api.harvest_backends"))