1
1
from unittest .mock import patch , MagicMock
2
- from db import search_issues
3
- from schema import IssuesParams
2
+ from db import (
3
+ search_issues ,
4
+ duck_db_connection ,
5
+ search_provision_summary ,
6
+ search_issue_type_summary ,
7
+ search_dataset_resource_mapping ,
8
+ search_endpoint_dataset_summary ,
9
+ get_specification ,
10
+ )
11
+ from schema import (
12
+ IssuesParams ,
13
+ IssueTypeSummaryParams ,
14
+ CommonParams ,
15
+ SpecificationsParams ,
16
+ )
4
17
from pagination_model import PaginatedResult
5
18
import pytest
19
+ import json
6
20
21
+ # Mock data
22
+ mock_results_data = [
23
+ {
24
+ "dataset" : "conservation-area" ,
25
+ "resource" : "0b4284077da580a6daea59ee2227f9c7c55a9a45d57ef470d82418a4391ddf9a" ,
26
+ },
27
+ {
28
+ "dataset" : "conservation-area" ,
29
+ "resource" : "test" ,
30
+ },
31
+ ]
32
+ mock_count = 2
7
33
8
- def test_search_issues ():
9
- # Prepare test params
10
- params = IssuesParams (
11
- dataset = "conservation-area" ,
12
- resource = None ,
13
- field = None ,
14
- issue_type = None ,
34
+
35
+ @pytest .fixture
36
+ def sample_query_params ():
37
+ return ["sample_value" ]
38
+
39
+
40
+ @pytest .fixture
41
+ def sample_sql_count ():
42
+ return "SELECT COUNT(*) FROM sample_table WHERE column = ?"
43
+
44
+
45
+ @pytest .fixture
46
+ def sample_sql_results ():
47
+ return "SELECT * FROM sample_table WHERE column = ? LIMIT ? OFFSET ?"
48
+
49
+
50
+ @pytest .fixture
51
+ def sample_issue_params ():
52
+ return IssuesParams (
53
+ dataset = "sample_dataset" ,
54
+ resource = "abc123" ,
55
+ field = "geometry" ,
56
+ issue_type = "sample_issue" ,
15
57
limit = 10 ,
16
58
offset = 0 ,
17
59
)
18
60
19
- # Mock data
20
- mock_results_data = [
21
- {
22
- "dataset" : "conservation-area" ,
23
- "resource" : "0b4284077da580a6daea59ee2227f9c7c55a9a45d57ef470d82418a4391ddf9a" ,
24
- },
25
- {
26
- "dataset" : "conservation-area" ,
27
- "resource" : "test" ,
28
- },
29
- ]
30
- mock_count = 2
31
61
62
+ @pytest .fixture
63
+ def sample_issue_type_params ():
64
+ return IssueTypeSummaryParams (
65
+ dataset = "sample_dataset" ,
66
+ organisation = "sample_org" ,
67
+ issueType = "sample_issue" ,
68
+ issueField = None ,
69
+ severity = None ,
70
+ responsibility = None ,
71
+ limit = 10 ,
72
+ offset = 0 ,
73
+ )
74
+
75
+
76
+ @pytest .fixture
77
+ def sample_common_params ():
78
+ return CommonParams (
79
+ dataset = "sample_dataset" , organisation = "sample_org" , limit = 10 , offset = 0
80
+ )
81
+
82
+
83
+ @pytest .fixture
84
+ def sample_specification_params ():
85
+ return SpecificationsParams (dataset = "sample_dataset" , limit = 10 , offset = 0 )
86
+
87
+
88
+ @patch ("duckdb.connect" )
89
+ def test_search_issues (mock_connect , sample_issue_params ):
32
90
# Mock `duckdb.connect`
33
- with patch ("duckdb.connect" ) as mock_connect :
34
- mock_conn = MagicMock ()
35
- mock_connect .return_value .__enter__ .return_value = mock_conn
36
91
37
- mock_cursor = MagicMock ()
38
- mock_cursor .fetchone .return_value = (mock_count ,)
39
- mock_cursor .arrow .return_value .to_pylist .return_value = mock_results_data
40
- mock_conn .execute .return_value = mock_cursor
92
+ mock_conn = MagicMock ()
93
+ mock_connect .return_value .__enter__ .return_value = mock_conn
94
+
95
+ mock_cursor = MagicMock ()
96
+ mock_cursor .fetchone .return_value = (mock_count ,)
97
+ mock_cursor .arrow .return_value .to_pylist .return_value = mock_results_data
98
+ mock_conn .execute .return_value = mock_cursor
41
99
42
- result = search_issues (params )
100
+ result = search_issues (sample_issue_params )
43
101
44
102
# Validate the results from the search
45
103
assert isinstance (result , PaginatedResult )
@@ -62,3 +120,173 @@ def test_search_issues_no_dataset():
62
120
IssuesParams (
63
121
dataset = None , resource = None , field = None , issue_type = None , limit = 10 , offset = 0
64
122
)
123
+
124
+
125
+ @patch ("duckdb.connect" )
126
+ def test_search_provision_summary (mock_connect , sample_common_params ):
127
+ """Test search_issue_type_summary with mocked DuckDB connection."""
128
+ mock_conn = MagicMock ()
129
+ mock_cursor = MagicMock ()
130
+
131
+ # Mock query results
132
+ mock_cursor .fetchone .return_value = [5 ] # Simulated COUNT(*) result
133
+ mock_cursor .arrow .return_value .to_pylist .return_value = [
134
+ {
135
+ "organisation" : "org1" ,
136
+ "dataset" : "data1" ,
137
+ "active_endpoint_count" : 0 ,
138
+ "error_endpoint_count" : 0 ,
139
+ },
140
+ {
141
+ "organisation" : "org2" ,
142
+ "dataset" : "data2" ,
143
+ "active_endpoint_count" : 4 ,
144
+ "error_endpoint_count" : 1 ,
145
+ },
146
+ {
147
+ "organisation" : "org3" ,
148
+ "dataset" : "data3" ,
149
+ "active_endpoint_count" : 5 ,
150
+ "error_endpoint_count" : 3 ,
151
+ },
152
+ ]
153
+
154
+ mock_conn .execute .return_value = mock_cursor
155
+ mock_connect .return_value .__enter__ .return_value = mock_conn
156
+
157
+ result = search_provision_summary (sample_common_params )
158
+
159
+ assert isinstance (result , PaginatedResult )
160
+ assert result .total_results_available == 5
161
+ assert len (result .data ) == 3
162
+ assert result .data [0 ]["organisation" ] == "org1"
163
+
164
+
165
+ @patch ("duckdb.connect" )
166
+ def test_search_issue_type_summary (mock_connect , sample_issue_type_params ):
167
+ """Test search_issue_type_summary with mocked DuckDB connection."""
168
+ mock_conn = MagicMock ()
169
+ mock_cursor = MagicMock ()
170
+
171
+ # Mock query results
172
+ mock_cursor .fetchone .return_value = [5 ] # Simulated COUNT(*) result
173
+ mock_cursor .arrow .return_value .to_pylist .return_value = [
174
+ {
175
+ "organisation" : "org1" ,
176
+ "dataset" : "data1" ,
177
+ "issue_type" : "type1" ,
178
+ "field" : "field1" ,
179
+ },
180
+ {
181
+ "organisation" : "org2" ,
182
+ "dataset" : "data2" ,
183
+ "issue_type" : "type2" ,
184
+ "field" : "field2" ,
185
+ },
186
+ ]
187
+
188
+ mock_conn .execute .return_value = mock_cursor
189
+ mock_connect .return_value .__enter__ .return_value = mock_conn
190
+
191
+ result = search_issue_type_summary (sample_issue_type_params )
192
+
193
+ assert isinstance (result , PaginatedResult )
194
+ assert result .total_results_available == 5
195
+ assert len (result .data ) == 2
196
+ assert result .data [0 ]["issue_type" ] == "type1"
197
+
198
+
199
+ @patch ("duckdb.connect" )
200
+ def test_search_dataset_resource_mapping (mock_connect , sample_common_params ):
201
+ """Test search_dataset_resource_mapping with mocked DuckDB connection."""
202
+ mock_conn = MagicMock ()
203
+ mock_cursor = MagicMock ()
204
+
205
+ mock_cursor .fetchone .return_value = [3 ] # Simulated COUNT(*) result
206
+ mock_cursor .arrow .return_value .to_pylist .return_value = [
207
+ {"dataset" : "data1" , "resource" : "res1" },
208
+ {"dataset" : "data2" , "resource" : "res2" },
209
+ ]
210
+
211
+ mock_conn .execute .return_value = mock_cursor
212
+ mock_connect .return_value .__enter__ .return_value = mock_conn
213
+
214
+ result = search_dataset_resource_mapping (sample_common_params )
215
+
216
+ assert isinstance (result , PaginatedResult )
217
+ assert result .total_results_available == 3
218
+ assert len (result .data ) == 2
219
+ assert result .data [1 ]["dataset" ] == "data2"
220
+
221
+
222
+ @patch ("duckdb.connect" )
223
+ def test_search_endpoint_dataset_summary (mock_connect , sample_common_params ):
224
+ """Test search_endpoint_dataset_summary with mocked DuckDB connection."""
225
+ mock_conn = MagicMock ()
226
+ mock_cursor = MagicMock ()
227
+
228
+ mock_cursor .fetchone .return_value = [8 ] # Simulated COUNT(*) result
229
+ mock_cursor .arrow .return_value .to_pylist .return_value = [
230
+ {"dataset" : "data1" , "endpoint" : "endpoint1" },
231
+ {"dataset" : "data2" , "endpoint" : "endpoint2" },
232
+ ]
233
+
234
+ mock_conn .execute .return_value = mock_cursor
235
+ mock_connect .return_value .__enter__ .return_value = mock_conn
236
+
237
+ result = search_endpoint_dataset_summary (sample_common_params )
238
+
239
+ assert isinstance (result , PaginatedResult )
240
+ assert result .total_results_available == 8
241
+ assert len (result .data ) == 2
242
+ assert result .data [0 ]["endpoint" ] == "endpoint1"
243
+
244
+
245
+ @patch ("duckdb.connect" )
246
+ def test_get_specification (mock_connect , sample_specification_params , caplog ):
247
+ """Test get_specification with mocked DuckDB connection."""
248
+ mock_conn = MagicMock ()
249
+ mock_cursor = MagicMock ()
250
+
251
+ # Mock COUNT(*) result
252
+ mock_cursor .fetchone .return_value = [3 ]
253
+
254
+ # Mock JSON data results
255
+ mock_cursor .arrow .return_value .to_pylist .return_value = [
256
+ {"json" : json .dumps ({"dataset" : "test_dataset" , "spec" : "value1" })},
257
+ {"json" : json .dumps ({"dataset" : "test_dataset" , "spec" : "value2" })},
258
+ ]
259
+
260
+ mock_conn .execute .return_value = mock_cursor
261
+ mock_connect .return_value .__enter__ .return_value = mock_conn
262
+
263
+ result = get_specification (sample_specification_params )
264
+
265
+ # Assertions on return value
266
+ assert isinstance (result , PaginatedResult )
267
+ assert result .total_results_available == 3
268
+ assert len (result .data ) == 2
269
+ assert result .data [0 ]["dataset" ] == "test_dataset"
270
+ assert result .data [1 ]["spec" ] == "value2"
271
+
272
+
273
+ @patch ("duckdb.connect" )
274
+ def test_duck_db_connection_exception (
275
+ mock_connect ,
276
+ sample_issue_params ,
277
+ sample_query_params ,
278
+ sample_sql_count ,
279
+ sample_sql_results ,
280
+ ):
281
+ mock_conn = MagicMock ()
282
+ mock_conn .execute .side_effect = Exception ("Database error" ) # Simulate an error
283
+
284
+ mock_connect .return_value .__enter__ .return_value = mock_conn
285
+
286
+ with pytest .raises (Exception , match = "Database error" ):
287
+ duck_db_connection (
288
+ sample_issue_params ,
289
+ sample_query_params ,
290
+ sample_sql_count ,
291
+ sample_sql_results ,
292
+ )
0 commit comments