ara-cli 0.1.9.50__py3-none-any.whl → 0.1.9.52__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.
@@ -1,6 +1,7 @@
1
1
  import pytest
2
2
  from unittest.mock import MagicMock, patch
3
3
  from ara_cli.artefact_lister import ArtefactLister
4
+ from ara_cli.list_filter import ListFilter
4
5
 
5
6
 
6
7
  @pytest.fixture
@@ -8,197 +9,623 @@ def artefact_lister():
8
9
  return ArtefactLister()
9
10
 
10
11
 
11
- @pytest.mark.parametrize("artefact_content, artefact_path", [
12
- ("content1", "path1"),
13
- ("content2", "path2"),
14
- ("content3", "path3"),
15
- ])
16
- def test_artefact_content_retrieval(artefact_content, artefact_path):
12
+ @pytest.mark.parametrize(
13
+ "users, status, tags, expected_tags",
14
+ [
15
+ # Normal case with all fields populated
16
+ (
17
+ ["john", "alice"],
18
+ "in-progress",
19
+ ["important", "urgent"],
20
+ ["user_john", "user_alice", "in-progress", "important", "urgent"]
21
+ ),
22
+ # Case with empty users
23
+ (
24
+ [],
25
+ "to-do",
26
+ ["feature", "backend"],
27
+ ["to-do", "feature", "backend"]
28
+ ),
29
+ # Case with empty tags
30
+ (
31
+ ["bob"],
32
+ "done",
33
+ [],
34
+ ["user_bob", "done"]
35
+ ),
36
+ # Case with all empty fields
37
+ (
38
+ [],
39
+ "",
40
+ [],
41
+ [""]
42
+ ),
43
+ # Case with None values for tags (should handle gracefully)
44
+ (
45
+ ["admin"],
46
+ "closed",
47
+ None,
48
+ ["user_admin", "closed"]
49
+ ),
50
+ ]
51
+ )
52
+ def test_artefact_tags_retrieval(users, status, tags, expected_tags):
53
+ # Create a mock artefact with the specified attributes
17
54
  artefact_mock = MagicMock()
18
- artefact_mock.content = artefact_content
19
- artefact_mock.file_path = artefact_path
55
+ artefact_mock.users = users
56
+ artefact_mock.status = status
57
+ artefact_mock.tags = tags if tags is not None else []
58
+
59
+ # Call the method under test
60
+ result = ArtefactLister.artefact_tags_retrieval(artefact_mock)
61
+
62
+ # Verify the result
63
+ assert result == expected_tags
64
+
65
+
66
+ def test_artefact_tags_retrieval_with_none():
67
+ # Test with None artefact
68
+ result = ArtefactLister.artefact_tags_retrieval(None)
69
+ assert result == []
70
+
71
+
72
+ @pytest.mark.parametrize(
73
+ "classified_files, list_filter, filter_result",
74
+ [
75
+ # Case 1: No filter applied
76
+ (
77
+ {"type1": [MagicMock(), MagicMock()]},
78
+ None,
79
+ {"type1": [MagicMock(), MagicMock()]}
80
+ ),
81
+ # Case 2: Filter with include tags
82
+ (
83
+ {"type1": [MagicMock(), MagicMock()]},
84
+ ListFilter(include_tags=["tag1"]),
85
+ {"type1": [MagicMock()]}
86
+ ),
87
+ # Case 3: Filter with exclude tags
88
+ (
89
+ {"type1": [MagicMock(), MagicMock()], "type2": [MagicMock()]},
90
+ ListFilter(exclude_tags=["tag2"]),
91
+ {"type1": [MagicMock()], "type2": []}
92
+ ),
93
+ # Case 4: Empty result after filtering
94
+ (
95
+ {"type1": [MagicMock(), MagicMock()]},
96
+ ListFilter(include_tags=["nonexistent"]),
97
+ {"type1": []}
98
+ ),
99
+ # Case 5: Multiple artefact types
100
+ (
101
+ {"type1": [MagicMock()], "type2": [MagicMock(), MagicMock()]},
102
+ ListFilter(exclude_extension=[".txt"]),
103
+ {"type1": [], "type2": [MagicMock()]}
104
+ ),
105
+ ],
106
+ )
107
+ def test_filter_artefacts(
108
+ artefact_lister,
109
+ classified_files,
110
+ list_filter,
111
+ filter_result
112
+ ):
113
+ # Mock the filter_list function
114
+ with patch("ara_cli.artefact_lister.filter_list") as mock_filter_list:
115
+ mock_filter_list.return_value = filter_result
116
+
117
+ # Call the method under test
118
+ result = artefact_lister.filter_artefacts(classified_files, list_filter)
119
+
120
+ # Verify filter_list was called with correct parameters
121
+ mock_filter_list.assert_called_once_with(
122
+ list_to_filter=classified_files,
123
+ list_filter=list_filter,
124
+ content_retrieval_strategy=ArtefactLister.artefact_content_retrieval,
125
+ file_path_retrieval=ArtefactLister.artefact_path_retrieval,
126
+ tag_retrieval=ArtefactLister.artefact_tags_retrieval
127
+ )
20
128
 
21
- content = ArtefactLister.artefact_content_retrieval(artefact_mock)
22
- assert content == artefact_content
129
+ # Verify the structure matches (don't compare the actual MagicMock objects)
130
+ assert set(result.keys()) == set(filter_result.keys())
131
+ for key in filter_result:
132
+ assert len(result[key]) == len(filter_result[key])
23
133
 
24
134
 
25
- @pytest.mark.parametrize("artefact_content, artefact_path", [
26
- ("content1", "path1"),
27
- ("content2", "path2"),
28
- ("content3", "path3"),
29
- ])
30
- def test_artefact_path_retrieval(artefact_content, artefact_path):
135
+ @pytest.mark.parametrize("artefact_content", ["content1", "content2", "content3"])
136
+ def test_artefact_content_retrieval(artefact_content):
31
137
  artefact_mock = MagicMock()
32
- artefact_mock.content = artefact_content
33
- artefact_mock.file_path = artefact_path
34
-
35
- path = ArtefactLister.artefact_path_retrieval(artefact_mock)
36
- assert path == artefact_path
37
-
38
-
39
- @pytest.mark.parametrize("tags, navigate_to_target", [
40
- (None, False),
41
- (["tag1", "tag2"], False),
42
- (["tag1"], True),
43
- ([], True)
44
- ])
45
- @patch('ara_cli.artefact_lister.FileClassifier')
46
- @patch('ara_cli.artefact_lister.DirectoryNavigator')
47
- def test_list_files(mock_directory_navigator, mock_file_classifier, artefact_lister, tags, navigate_to_target):
48
- mock_navigator_instance = mock_directory_navigator.return_value
49
- mock_navigator_instance.navigate_to_target = MagicMock()
50
-
51
- mock_classifier_instance = mock_file_classifier.return_value
52
- mock_classifier_instance.classify_files = MagicMock(return_value={'mocked_files': []})
53
- mock_classifier_instance.print_classified_files = MagicMock()
54
-
55
- artefact_lister.list_files(tags=tags, navigate_to_target=navigate_to_target)
56
-
57
- if navigate_to_target:
58
- mock_navigator_instance.navigate_to_target.assert_called_once()
59
- else:
60
- mock_navigator_instance.navigate_to_target.assert_not_called()
61
-
62
- mock_classifier_instance.classify_files.assert_called_once_with(tags=tags)
63
-
64
- mock_classifier_instance.print_classified_files.assert_called_once_with({'mocked_files': []})
138
+ artefact_mock.serialize.return_value = artefact_content # Mock serialize()
65
139
 
140
+ content = ArtefactLister.artefact_content_retrieval(artefact_mock)
141
+ assert content == artefact_content
66
142
 
67
- @pytest.mark.parametrize("classifier, artefact_name, classified_artefacts, expected_suggestions", [
68
- ("classifier1", "missing_artefact", {"classifier1": []}, []),
69
- ("classifier2", "artefact1", {"classifier2": [MagicMock(file_name="artefact1")]}, None)
70
- ])
71
- @patch('ara_cli.artefact_lister.FileClassifier')
72
- @patch('ara_cli.artefact_lister.suggest_close_name_matches')
73
- @patch('ara_cli.artefact_lister.ArtefactReader')
74
- def test_list_branch_no_match(mock_artefact_reader, mock_suggest, mock_file_classifier, classifier, artefact_name, classified_artefacts, expected_suggestions, artefact_lister):
75
- mock_classifier_instance = mock_file_classifier.return_value
76
- mock_classifier_instance.classify_files = MagicMock(return_value=classified_artefacts)
77
- mock_classifier_instance.print_classified_files = MagicMock()
78
143
 
79
- mock_artefact_reader.step_through_value_chain = MagicMock()
144
+ @pytest.mark.parametrize(
145
+ "file_path",
146
+ [
147
+ ("./ara/userstories/test.userstory"),
148
+ ("./ara/epics/test.epic"),
149
+ ],
150
+ )
151
+ def test_artefact_path_retrieval(file_path):
152
+ artefact_mock = MagicMock()
153
+ artefact_mock.file_path = file_path
80
154
 
81
- artefact_lister.list_branch(classifier, artefact_name)
155
+ path = ArtefactLister.artefact_path_retrieval(artefact_mock)
156
+ assert path == file_path
157
+
158
+
159
+ @pytest.mark.parametrize(
160
+ "tags, navigate_to_target, list_filter, mock_artefacts, filtered_artefacts, expected_filtered",
161
+ [
162
+ # Test with no filter
163
+ (
164
+ None,
165
+ False,
166
+ None,
167
+ {"type1": [MagicMock(), MagicMock()]},
168
+ {"type1": [MagicMock(), MagicMock()]},
169
+ {"type1": [MagicMock(), MagicMock()]},
170
+ ),
171
+ # Test with filter applied
172
+ (
173
+ ["tag1"],
174
+ False,
175
+ ListFilter(include_tags=["tag1"]),
176
+ {"type1": [MagicMock(), MagicMock()]},
177
+ {"type1": [MagicMock()]},
178
+ {"type1": [MagicMock()]},
179
+ ),
180
+ # Test with None values in artefact list
181
+ (
182
+ None,
183
+ False,
184
+ None,
185
+ {"type1": [MagicMock(), None, MagicMock()]},
186
+ {"type1": [MagicMock(), None, MagicMock()]},
187
+ {"type1": [MagicMock(), MagicMock()]},
188
+ ),
189
+ # Test with empty filtered results
190
+ (
191
+ ["tag1"],
192
+ False,
193
+ ListFilter(include_tags=["nonexistent"]),
194
+ {"type1": [MagicMock(), MagicMock()]},
195
+ {"type1": []},
196
+ {"type1": []},
197
+ ),
198
+ # Test with multiple artefact types
199
+ (
200
+ None,
201
+ True,
202
+ ListFilter(exclude_extension=[".txt"]),
203
+ {"type1": [MagicMock()], "type2": [MagicMock(), MagicMock()]},
204
+ {"type1": [], "type2": [MagicMock()]},
205
+ {"type1": [], "type2": [MagicMock()]},
206
+ ),
207
+ ],
208
+ )
209
+ def test_list_files(
210
+ artefact_lister,
211
+ tags,
212
+ navigate_to_target,
213
+ list_filter,
214
+ mock_artefacts,
215
+ filtered_artefacts,
216
+ expected_filtered,
217
+ ):
218
+ # Mock ArtefactReader.read_artefacts
219
+ with patch("ara_cli.artefact_lister.ArtefactReader") as mock_reader:
220
+ mock_reader.read_artefacts.return_value = mock_artefacts
221
+
222
+ # Mock filter_artefacts method
223
+ artefact_lister.filter_artefacts = MagicMock(return_value=filtered_artefacts)
224
+
225
+ # Mock FileClassifier
226
+ with patch("ara_cli.artefact_lister.FileClassifier") as mock_file_classifier:
227
+ mock_classifier_instance = MagicMock()
228
+ mock_file_classifier.return_value = mock_classifier_instance
229
+
230
+ # Call the method under test
231
+ artefact_lister.list_files(
232
+ tags=tags,
233
+ navigate_to_target=navigate_to_target,
234
+ list_filter=list_filter,
235
+ )
236
+
237
+ # Verify the correct calls were made
238
+ mock_reader.read_artefacts.assert_called_once_with(tags=tags)
239
+ artefact_lister.filter_artefacts.assert_called_once_with(
240
+ mock_artefacts, list_filter
241
+ )
242
+
243
+ # Check that the correct filtered list is passed to print_classified_files
244
+ # We need to check structure rather than exact equality because MagicMock instances are different
245
+ call_arg = mock_classifier_instance.print_classified_files.call_args[0][0]
246
+
247
+ # Verify structure matches expected filtered artefacts
248
+ assert set(call_arg.keys()) == set(expected_filtered.keys())
249
+ for key in expected_filtered:
250
+ assert len(call_arg[key]) == len(expected_filtered[key])
251
+
252
+ # Verify FileClassifier was initialized with the correct file system
253
+ mock_file_classifier.assert_called_once_with(artefact_lister.file_system)
254
+
255
+
256
+ @pytest.mark.parametrize(
257
+ "classifier, artefact_name, list_filter, classified_artefacts, artefact_info, matching_artefacts, child_artefacts, filtered_artefacts",
258
+ [
259
+ # Case 1: Artefact found, with children, no filter
260
+ (
261
+ "epic",
262
+ "Epic1",
263
+ None,
264
+ {"epic": [{"title": "Epic1"}, {"title": "Epic2"}]},
265
+ [{"title": "Epic1"}, {"title": "Epic2"}],
266
+ [{"title": "Epic1"}],
267
+ {"userstory": ["Story1", "Story2"]},
268
+ {"userstory": ["Story1", "Story2"]},
269
+ ),
270
+ # Case 2: Artefact found, with children, with filter
271
+ (
272
+ "epic",
273
+ "Epic1",
274
+ ListFilter(include_tags=["tag1"]),
275
+ {"epic": [{"title": "Epic1"}, {"title": "Epic2"}]},
276
+ [{"title": "Epic1"}, {"title": "Epic2"}],
277
+ [{"title": "Epic1"}],
278
+ {"userstory": ["Story1", "Story2"]},
279
+ {"userstory": ["Story1"]}, # Filtered result
280
+ ),
281
+ # Case 3: Artefact not found
282
+ (
283
+ "epic",
284
+ "NonExistentEpic",
285
+ None,
286
+ {"epic": [{"title": "Epic1"}, {"title": "Epic2"}]},
287
+ [{"title": "Epic1"}, {"title": "Epic2"}],
288
+ [],
289
+ {},
290
+ {},
291
+ ),
292
+ ],
293
+ )
294
+ def test_list_children(
295
+ artefact_lister,
296
+ classifier,
297
+ artefact_name,
298
+ list_filter,
299
+ classified_artefacts,
300
+ artefact_info,
301
+ matching_artefacts,
302
+ child_artefacts,
303
+ filtered_artefacts,
304
+ ):
305
+ # Setup mocks
306
+ with patch("ara_cli.artefact_lister.FileClassifier") as mock_file_classifier, patch(
307
+ "ara_cli.artefact_lister.suggest_close_name_matches"
308
+ ) as mock_suggest, patch(
309
+ "ara_cli.artefact_lister.ArtefactReader"
310
+ ) as mock_artefact_reader:
311
+
312
+ # Configure mock FileClassifier
313
+ mock_classifier_instance = MagicMock()
314
+ mock_file_classifier.return_value = mock_classifier_instance
315
+ mock_classifier_instance.classify_files.return_value = classified_artefacts
316
+
317
+ # Configure ArtefactReader mock
318
+ mock_artefact_reader.find_children.return_value = child_artefacts
319
+
320
+ # Mock filter_artefacts method
321
+ artefact_lister.filter_artefacts = MagicMock(return_value=filtered_artefacts)
322
+
323
+ # Call the method under test
324
+ artefact_lister.list_children(classifier, artefact_name, list_filter)
325
+
326
+ # Verify interactions
327
+ mock_classifier_instance.classify_files.assert_called_once()
328
+
329
+ # Check if suggestions were made for non-existent artefacts
330
+ if not matching_artefacts:
331
+ mock_suggest.assert_called_once_with(
332
+ artefact_name, [info["title"] for info in artefact_info]
333
+ )
334
+ else:
335
+ mock_suggest.assert_not_called()
336
+
337
+ # Verify ArtefactReader.find_children was called
338
+ mock_artefact_reader.find_children.assert_called_once_with(
339
+ artefact_name=artefact_name, classifier=classifier
340
+ )
82
341
 
83
- if expected_suggestions is not None:
84
- mock_suggest.assert_called_once_with(artefact_name, [])
85
- mock_artefact_reader.step_through_value_chain.assert_not_called()
86
- mock_classifier_instance.print_classified_files.assert_not_called()
87
- else:
88
- mock_suggest.assert_not_called()
89
- mock_artefact_reader.step_through_value_chain.assert_called_once_with(
90
- artefact_name=artefact_name,
91
- classifier=classifier,
92
- artefacts_by_classifier={classifier: []}
342
+ # Verify filter_artefacts was called with correct parameters
343
+ artefact_lister.filter_artefacts.assert_called_once_with(
344
+ child_artefacts, list_filter
93
345
  )
94
- mock_classifier_instance.print_classified_files.assert_called_once()
95
346
 
347
+ # Verify print_classified_files was called with filtered results
348
+ mock_classifier_instance.print_classified_files.assert_called_once_with(
349
+ filtered_artefacts
350
+ )
96
351
 
97
- @pytest.mark.parametrize("classifier, artefact_name, classified_artefacts, expected_suggestions", [
98
- ("classifier1", "missing_artefact", {"classifier1": []}, []),
99
- ("classifier2", "artefact1", {"classifier2": [MagicMock(file_name="artefact1")]}, None)
100
- ])
101
- @patch('ara_cli.artefact_lister.FileClassifier')
102
- @patch('ara_cli.artefact_lister.suggest_close_name_matches')
103
- @patch('ara_cli.artefact_lister.ArtefactReader')
104
- def test_list_children_no_match(mock_artefact_reader, mock_suggest, mock_file_classifier, classifier, artefact_name, classified_artefacts, expected_suggestions, artefact_lister):
105
- # Mock the FileClassifier and its methods
106
- mock_classifier_instance = mock_file_classifier.return_value
107
- mock_classifier_instance.classify_files = MagicMock(return_value=classified_artefacts)
108
- mock_classifier_instance.print_classified_files = MagicMock()
109
352
 
110
- mock_artefact_reader.find_children = MagicMock()
353
+ @pytest.mark.parametrize(
354
+ "classifier, artefact_name, list_filter, classified_artefacts, artefact_info, matching_artefacts, value_chain_artefacts, filtered_artefacts",
355
+ [
356
+ # Case 1: Artefact found, with value chain, no filter
357
+ (
358
+ "epic",
359
+ "Epic1",
360
+ None,
361
+ {"epic": [{"title": "Epic1"}, {"title": "Epic2"}]},
362
+ [{"title": "Epic1"}, {"title": "Epic2"}],
363
+ [{"title": "Epic1"}],
364
+ {"epic": ["Epic1"], "userstory": ["Story1", "Story2"]},
365
+ {"epic": ["Epic1"], "userstory": ["Story1", "Story2"]},
366
+ ),
367
+ # Case 2: Artefact found, with value chain, with filter
368
+ (
369
+ "epic",
370
+ "Epic1",
371
+ ListFilter(include_tags=["tag1"]),
372
+ {"epic": [{"title": "Epic1"}, {"title": "Epic2"}]},
373
+ [{"title": "Epic1"}, {"title": "Epic2"}],
374
+ [{"title": "Epic1"}],
375
+ {"epic": ["Epic1"], "userstory": ["Story1", "Story2"]},
376
+ {"epic": ["Epic1"], "userstory": ["Story1"]}, # Filtered result
377
+ ),
378
+ # Case 3: Artefact not found
379
+ (
380
+ "epic",
381
+ "NonExistentEpic",
382
+ None,
383
+ {"epic": [{"title": "Epic1"}, {"title": "Epic2"}]},
384
+ [{"title": "Epic1"}, {"title": "Epic2"}],
385
+ [],
386
+ {"epic": []},
387
+ {"epic": []},
388
+ ),
389
+ # Case 4: Empty artefact list
390
+ (
391
+ "epic",
392
+ "Epic1",
393
+ None,
394
+ {"epic": []},
395
+ [],
396
+ [],
397
+ {"epic": []},
398
+ {"epic": []},
399
+ ),
400
+ ],
401
+ )
402
+ def test_list_branch(
403
+ artefact_lister,
404
+ classifier,
405
+ artefact_name,
406
+ list_filter,
407
+ classified_artefacts,
408
+ artefact_info,
409
+ matching_artefacts,
410
+ value_chain_artefacts,
411
+ filtered_artefacts,
412
+ ):
413
+ # Setup mocks
414
+ with patch("ara_cli.artefact_lister.FileClassifier") as mock_file_classifier, patch(
415
+ "ara_cli.artefact_lister.suggest_close_name_matches"
416
+ ) as mock_suggest, patch(
417
+ "ara_cli.artefact_lister.ArtefactReader"
418
+ ) as mock_artefact_reader, patch(
419
+ "ara_cli.artefact_lister.os"
420
+ ) as mock_os:
421
+
422
+ # Configure mock FileClassifier
423
+ mock_classifier_instance = MagicMock()
424
+ mock_file_classifier.return_value = mock_classifier_instance
425
+ mock_classifier_instance.classify_files.return_value = classified_artefacts
426
+
427
+ # Mock step_through_value_chain to modify the provided dictionary
428
+ def mock_step_through(artefact_name, classifier, artefacts_by_classifier):
429
+ # Replace the artefacts_by_classifier with our test data
430
+ for k, v in value_chain_artefacts.items():
431
+ artefacts_by_classifier[k] = v
432
+
433
+ mock_artefact_reader.step_through_value_chain.side_effect = mock_step_through
434
+
435
+ # Mock filter_artefacts method
436
+ artefact_lister.filter_artefacts = MagicMock(return_value=filtered_artefacts)
437
+
438
+ # Call the method under test
439
+ artefact_lister.list_branch(classifier, artefact_name, list_filter)
440
+
441
+ # Verify interactions
442
+ mock_file_classifier.assert_called_once_with(mock_os)
443
+ mock_classifier_instance.classify_files.assert_called_once()
444
+
445
+ # Check if suggestions were made for non-existent artefacts
446
+ if not matching_artefacts:
447
+ mock_suggest.assert_called_once_with(
448
+ artefact_name, [info["title"] for info in artefact_info]
449
+ )
450
+ else:
451
+ mock_suggest.assert_not_called()
452
+
453
+ # Verify ArtefactReader.step_through_value_chain was called with correct parameters
454
+ mock_artefact_reader.step_through_value_chain.assert_called_once()
455
+ call_args = mock_artefact_reader.step_through_value_chain.call_args[1]
456
+ assert call_args["artefact_name"] == artefact_name
457
+ assert call_args["classifier"] == classifier
458
+ assert classifier in call_args["artefacts_by_classifier"]
459
+
460
+ # Verify filter_artefacts was called with correct parameters
461
+ # The exact contents will have been modified by the mock_step_through function
462
+ artefact_lister.filter_artefacts.assert_called_once()
463
+ filter_args = artefact_lister.filter_artefacts.call_args[0]
464
+ assert filter_args[1] == list_filter
465
+
466
+ # Verify print_classified_files was called with filtered results
467
+ mock_classifier_instance.print_classified_files.assert_called_once_with(
468
+ filtered_artefacts
469
+ )
111
470
 
112
- artefact_lister.list_children(classifier, artefact_name)
113
471
 
114
- if expected_suggestions is not None:
115
- mock_suggest.assert_called_once_with(artefact_name, [])
116
- mock_artefact_reader.find_children.assert_not_called()
117
- mock_classifier_instance.print_classified_files.assert_not_called()
118
- else:
472
+ def test_list_data_artefact_found_data_exists(artefact_lister):
473
+ classifier = "epic"
474
+ artefact_name = "Epic1"
475
+ list_filter = None
476
+ classified_artefacts = {
477
+ "epic": [
478
+ {"title": "Epic1", "file_path": "path/to/Epic1.epic"},
479
+ {"title": "Epic2", "file_path": "path/to/Epic2.epic"}
480
+ ]
481
+ }
482
+
483
+ with patch("ara_cli.artefact_lister.FileClassifier") as mock_file_classifier, \
484
+ patch("ara_cli.artefact_lister.suggest_close_name_matches") as mock_suggest, \
485
+ patch("ara_cli.artefact_lister.os") as mock_os, \
486
+ patch("ara_cli.artefact_lister.list_files_in_directory") as mock_list_files:
487
+
488
+ # Configure mocks
489
+ mock_classifier_instance = MagicMock()
490
+ mock_file_classifier.return_value = mock_classifier_instance
491
+ mock_classifier_instance.classify_files.return_value = classified_artefacts
492
+
493
+ mock_os.path.splitext.return_value = ("path/to/Epic1", ".epic")
494
+ mock_os.path.exists.return_value = True
495
+
496
+ # Call the method under test
497
+ artefact_lister.list_data(classifier, artefact_name, list_filter)
498
+
499
+ # Verify interactions
119
500
  mock_suggest.assert_not_called()
120
- mock_artefact_reader.find_children.assert_called_once_with(
121
- artefact_name=artefact_name,
122
- classifier=classifier
123
- )
124
- mock_classifier_instance.print_classified_files.assert_called_once()
125
-
126
- @pytest.mark.parametrize("classifier, artefact_name, child_artefacts, filtered_child_artefacts", [
127
- ("classifier2", "artefact1", [MagicMock(), MagicMock()], [MagicMock()]),
128
- ])
129
- @patch('ara_cli.artefact_lister.FileClassifier')
130
- @patch('ara_cli.artefact_lister.filter_list')
131
- @patch('ara_cli.artefact_lister.ArtefactReader')
132
- def test_list_children_with_children(mock_artefact_reader, mock_filter_list, mock_file_classifier, classifier, artefact_name, child_artefacts, filtered_child_artefacts, artefact_lister):
133
- mock_classifier_instance = mock_file_classifier.return_value
134
- mock_classifier_instance.classify_files = MagicMock(return_value={classifier: [MagicMock(file_name=artefact_name)]})
135
- mock_classifier_instance.print_classified_files = MagicMock()
136
-
137
- mock_artefact_reader.find_children = MagicMock(return_value=child_artefacts)
138
-
139
- mock_filter_list.return_value = filtered_child_artefacts
140
-
141
- artefact_lister.list_children(classifier, artefact_name)
142
-
143
- mock_artefact_reader.find_children.assert_called_once_with(
144
- artefact_name=artefact_name,
145
- classifier=classifier
146
- )
147
-
148
- mock_filter_list.assert_called_once_with(
149
- list_to_filter=child_artefacts,
150
- list_filter=None,
151
- content_retrieval_strategy=ArtefactLister.artefact_content_retrieval,
152
- file_path_retrieval=ArtefactLister.artefact_path_retrieval,
153
- tag_retrieval=ArtefactLister.artefact_tags_retrieval
154
- )
155
-
156
- mock_classifier_instance.print_classified_files.assert_called_once_with(
157
- files_by_classifier=filtered_child_artefacts
158
- )
159
-
160
-
161
- @pytest.mark.parametrize("classifier, artefact_name, classified_artefacts, expected_suggestions", [
162
- ("classifier1", "missing_artefact", {"classifier1": []}, True),
163
- ])
164
- @patch('ara_cli.artefact_lister.FileClassifier')
165
- @patch('ara_cli.artefact_lister.suggest_close_name_matches')
166
- @patch('ara_cli.artefact_lister.ArtefactReader')
167
- def test_list_data_no_match(mock_artefact_reader, mock_suggest, mock_file_classifier, classifier, artefact_name, classified_artefacts, expected_suggestions, artefact_lister):
168
- mock_classifier_instance = mock_file_classifier.return_value
169
- mock_classifier_instance.classify_files = MagicMock(return_value=classified_artefacts)
170
-
171
- artefact_lister.list_data(classifier, artefact_name)
172
-
173
- if expected_suggestions:
174
- mock_suggest.assert_called_once_with(artefact_name, [])
175
- else:
501
+ mock_os.path.splitext.assert_called_with("path/to/Epic1.epic")
502
+ mock_os.path.exists.assert_called_with("path/to/Epic1.data")
503
+ mock_list_files.assert_called_once_with("path/to/Epic1.data", list_filter)
504
+
505
+
506
+ def test_list_data_artefact_found_data_not_exists(artefact_lister):
507
+ classifier = "epic"
508
+ artefact_name = "Epic1"
509
+ list_filter = None
510
+ classified_artefacts = {
511
+ "epic": [
512
+ {"title": "Epic1", "file_path": "path/to/Epic1.epic"},
513
+ {"title": "Epic2", "file_path": "path/to/Epic2.epic"}
514
+ ]
515
+ }
516
+
517
+ with patch("ara_cli.artefact_lister.FileClassifier") as mock_file_classifier, \
518
+ patch("ara_cli.artefact_lister.suggest_close_name_matches") as mock_suggest, \
519
+ patch("ara_cli.artefact_lister.os") as mock_os, \
520
+ patch("ara_cli.artefact_lister.list_files_in_directory") as mock_list_files:
521
+
522
+ # Configure mocks
523
+ mock_classifier_instance = MagicMock()
524
+ mock_file_classifier.return_value = mock_classifier_instance
525
+ mock_classifier_instance.classify_files.return_value = classified_artefacts
526
+
527
+ mock_os.path.splitext.return_value = ("path/to/Epic1", ".epic")
528
+ mock_os.path.exists.return_value = False
529
+
530
+ # Call the method under test
531
+ artefact_lister.list_data(classifier, artefact_name, list_filter)
532
+
533
+ # Verify interactions
176
534
  mock_suggest.assert_not_called()
535
+ mock_os.path.splitext.assert_called_with("path/to/Epic1.epic")
536
+ mock_os.path.exists.assert_called_with("path/to/Epic1.data")
537
+ mock_list_files.assert_not_called()
177
538
 
178
- @pytest.mark.parametrize("classifier, artefact_name, content, file_path, file_exists", [
179
- ("classifier2", "artefact1", "some content", "path/to/artefact", True),
180
- ("classifier2", "artefact1", "some content", "path/to/artefact", False)
181
- ])
182
- @patch('ara_cli.artefact_lister.FileClassifier')
183
- @patch('ara_cli.artefact_lister.ArtefactReader')
184
- @patch('ara_cli.artefact_lister.Artefact')
185
- @patch('ara_cli.artefact_lister.os.path')
186
- @patch('ara_cli.artefact_lister.list_files_in_directory')
187
- def test_list_data_with_match(mock_list_files, mock_os_path, mock_artefact, mock_artefact_reader, mock_file_classifier, classifier, artefact_name, content, file_path, file_exists, artefact_lister):
188
- mock_classifier_instance = mock_file_classifier.return_value
189
- mock_classifier_instance.classify_files = MagicMock(return_value={classifier: [MagicMock(file_name=artefact_name)]})
190
-
191
- mock_artefact_reader.read_artefact = MagicMock(return_value=(content, file_path))
192
-
193
- artefact_instance = MagicMock(name=artefact_name)
194
- mock_artefact.from_content = MagicMock(return_value=artefact_instance)
195
539
 
196
- mock_os_path.splitext = MagicMock(return_value=(file_path, '.ext'))
197
- mock_os_path.exists = MagicMock(return_value=file_exists)
540
+ def test_list_data_artefact_not_found(artefact_lister):
541
+ classifier = "epic"
542
+ artefact_name = "NonExistentEpic"
543
+ list_filter = None
544
+ classified_artefacts = {
545
+ "epic": [
546
+ {"title": "Epic1", "file_path": "path/to/Epic1.epic"},
547
+ {"title": "Epic2", "file_path": "path/to/Epic2.epic"}
548
+ ]
549
+ }
550
+
551
+ with patch("ara_cli.artefact_lister.FileClassifier") as mock_file_classifier, \
552
+ patch("ara_cli.artefact_lister.suggest_close_name_matches") as mock_suggest, \
553
+ patch("ara_cli.artefact_lister.os") as mock_os, \
554
+ patch("ara_cli.artefact_lister.list_files_in_directory") as mock_list_files:
555
+
556
+ # Configure mocks
557
+ mock_classifier_instance = MagicMock()
558
+ mock_file_classifier.return_value = mock_classifier_instance
559
+ mock_classifier_instance.classify_files.return_value = classified_artefacts
560
+
561
+ # Call the method under test
562
+ artefact_lister.list_data(classifier, artefact_name, list_filter)
563
+
564
+ # Verify interactions
565
+ mock_suggest.assert_called_once_with(
566
+ artefact_name,
567
+ ["Epic1", "Epic2"]
568
+ )
569
+ mock_os.path.splitext.assert_not_called()
570
+ mock_os.path.exists.assert_not_called()
571
+ mock_list_files.assert_not_called()
198
572
 
199
- artefact_lister.list_data(classifier, artefact_name)
200
573
 
201
- if file_exists:
202
- mock_list_files.assert_called_once_with(file_path + '.data', None)
203
- else:
574
+ def test_list_data_with_filter(artefact_lister):
575
+ classifier = "userstory"
576
+ artefact_name = "Story1"
577
+ list_filter = ListFilter(include_tags=["tag1"])
578
+ classified_artefacts = {
579
+ "userstory": [
580
+ {"title": "Story1", "file_path": "path/to/Story1.userstory"},
581
+ {"title": "Story2", "file_path": "path/to/Story2.userstory"}
582
+ ]
583
+ }
584
+
585
+ with patch("ara_cli.artefact_lister.FileClassifier") as mock_file_classifier, \
586
+ patch("ara_cli.artefact_lister.suggest_close_name_matches") as mock_suggest, \
587
+ patch("ara_cli.artefact_lister.os") as mock_os, \
588
+ patch("ara_cli.artefact_lister.list_files_in_directory") as mock_list_files:
589
+
590
+ # Configure mocks
591
+ mock_classifier_instance = MagicMock()
592
+ mock_file_classifier.return_value = mock_classifier_instance
593
+ mock_classifier_instance.classify_files.return_value = classified_artefacts
594
+
595
+ mock_os.path.splitext.return_value = ("path/to/Story1", ".userstory")
596
+ mock_os.path.exists.return_value = True
597
+
598
+ # Call the method under test
599
+ artefact_lister.list_data(classifier, artefact_name, list_filter)
600
+
601
+ # Verify interactions
602
+ mock_suggest.assert_not_called()
603
+ mock_os.path.splitext.assert_called_with("path/to/Story1.userstory")
604
+ mock_os.path.exists.assert_called_with("path/to/Story1.data")
605
+ mock_list_files.assert_called_once_with("path/to/Story1.data", list_filter)
606
+
607
+
608
+ def test_list_data_empty_artefact_list(artefact_lister):
609
+ classifier = "epic"
610
+ artefact_name = "Epic1"
611
+ list_filter = None
612
+ classified_artefacts = {"epic": []}
613
+
614
+ with patch("ara_cli.artefact_lister.FileClassifier") as mock_file_classifier, \
615
+ patch("ara_cli.artefact_lister.suggest_close_name_matches") as mock_suggest, \
616
+ patch("ara_cli.artefact_lister.os") as mock_os, \
617
+ patch("ara_cli.artefact_lister.list_files_in_directory") as mock_list_files:
618
+
619
+ # Configure mocks
620
+ mock_classifier_instance = MagicMock()
621
+ mock_file_classifier.return_value = mock_classifier_instance
622
+ mock_classifier_instance.classify_files.return_value = classified_artefacts
623
+
624
+ # Call the method under test
625
+ artefact_lister.list_data(classifier, artefact_name, list_filter)
626
+
627
+ # Verify interactions
628
+ mock_suggest.assert_called_once_with(artefact_name, [])
629
+ mock_os.path.splitext.assert_not_called()
630
+ mock_os.path.exists.assert_not_called()
204
631
  mock_list_files.assert_not_called()