ara-cli 0.1.9.73__py3-none-any.whl → 0.1.9.75__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 ara-cli might be problematic. Click here for more details.

Files changed (39) hide show
  1. ara_cli/ara_command_action.py +15 -15
  2. ara_cli/ara_command_parser.py +2 -1
  3. ara_cli/ara_config.py +181 -73
  4. ara_cli/artefact_autofix.py +130 -68
  5. ara_cli/artefact_creator.py +1 -1
  6. ara_cli/artefact_models/artefact_model.py +26 -7
  7. ara_cli/artefact_models/artefact_templates.py +47 -31
  8. ara_cli/artefact_models/businessgoal_artefact_model.py +23 -25
  9. ara_cli/artefact_models/epic_artefact_model.py +23 -24
  10. ara_cli/artefact_models/feature_artefact_model.py +76 -46
  11. ara_cli/artefact_models/keyfeature_artefact_model.py +21 -24
  12. ara_cli/artefact_models/task_artefact_model.py +73 -13
  13. ara_cli/artefact_models/userstory_artefact_model.py +22 -24
  14. ara_cli/artefact_models/vision_artefact_model.py +23 -42
  15. ara_cli/artefact_scan.py +55 -17
  16. ara_cli/chat.py +23 -5
  17. ara_cli/prompt_handler.py +4 -4
  18. ara_cli/tag_extractor.py +43 -28
  19. ara_cli/template_manager.py +3 -8
  20. ara_cli/version.py +1 -1
  21. {ara_cli-0.1.9.73.dist-info → ara_cli-0.1.9.75.dist-info}/METADATA +1 -1
  22. {ara_cli-0.1.9.73.dist-info → ara_cli-0.1.9.75.dist-info}/RECORD +29 -39
  23. tests/test_ara_config.py +420 -36
  24. tests/test_artefact_autofix.py +289 -25
  25. tests/test_artefact_scan.py +296 -35
  26. tests/test_chat.py +35 -15
  27. ara_cli/templates/template.businessgoal +0 -10
  28. ara_cli/templates/template.capability +0 -10
  29. ara_cli/templates/template.epic +0 -15
  30. ara_cli/templates/template.example +0 -6
  31. ara_cli/templates/template.feature +0 -26
  32. ara_cli/templates/template.issue +0 -14
  33. ara_cli/templates/template.keyfeature +0 -15
  34. ara_cli/templates/template.task +0 -6
  35. ara_cli/templates/template.userstory +0 -17
  36. ara_cli/templates/template.vision +0 -14
  37. {ara_cli-0.1.9.73.dist-info → ara_cli-0.1.9.75.dist-info}/WHEEL +0 -0
  38. {ara_cli-0.1.9.73.dist-info → ara_cli-0.1.9.75.dist-info}/entry_points.txt +0 -0
  39. {ara_cli-0.1.9.73.dist-info → ara_cli-0.1.9.75.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,253 @@
1
1
  import pytest
2
2
  from unittest.mock import patch, MagicMock, mock_open, call
3
- from ara_cli.artefact_scan import check_file, find_invalid_files, show_results
4
- from pydantic import ValidationError
3
+ from ara_cli.artefact_scan import (
4
+ check_file,
5
+ find_invalid_files,
6
+ show_results,
7
+ is_contribution_valid,
8
+ is_rule_valid,
9
+ check_contribution,
10
+ )
11
+
12
+
13
+ @pytest.mark.parametrize("contribution", [None, False, 0, "", []])
14
+ def test_check_contribution_none_contribution(contribution):
15
+ # Should return (True, None) if contribution is falsey
16
+ result = check_contribution(
17
+ contribution, classified_artefact_info={}, file_path="irrelevant"
18
+ )
19
+ assert result == (True, None)
20
+
21
+
22
+ def test_check_contribution_invalid_contribution(monkeypatch):
23
+ # If is_contribution_valid returns False, should return (False, custom_reason)
24
+ contribution = MagicMock()
25
+ contribution.classifier = "some_cls"
26
+ contribution.artefact_name = "some_art"
27
+ with patch(
28
+ "ara_cli.artefact_scan.is_contribution_valid", return_value=False
29
+ ) as mock_is_contrib, patch("ara_cli.artefact_scan.is_rule_valid") as mock_is_rule:
30
+ result = check_contribution(
31
+ contribution, classified_artefact_info={}, file_path="f"
32
+ )
33
+ assert result == (
34
+ False,
35
+ "Invalid Contribution Reference: The contribution references "
36
+ "'some_cls' artefact 'some_art' which does not exist.",
37
+ )
38
+ mock_is_contrib.assert_called_once_with(contribution, {})
39
+ mock_is_rule.assert_not_called()
40
+
41
+
42
+ def test_check_contribution_invalid_rule(monkeypatch):
43
+ # is_contribution_valid returns True, is_rule_valid returns False
44
+ contribution = MagicMock()
45
+ contribution.classifier = "c"
46
+ contribution.artefact_name = "a"
47
+ contribution.rule = "r"
48
+ with patch(
49
+ "ara_cli.artefact_scan.is_contribution_valid", return_value=True
50
+ ) as mock_is_contrib, patch(
51
+ "ara_cli.artefact_scan.is_rule_valid", return_value=False
52
+ ) as mock_is_rule:
53
+ result = check_contribution(
54
+ contribution, classified_artefact_info={"x": 1}, file_path="myfile"
55
+ )
56
+ assert result == (
57
+ False,
58
+ "Rule Mismatch: The contribution references rule 'r' which the parent c 'a' does not have.",
59
+ )
60
+ mock_is_contrib.assert_called_once_with(contribution, {"x": 1})
61
+ mock_is_rule.assert_called_once_with(contribution, {"x": 1})
62
+
63
+
64
+ def test_check_contribution_all_valid(monkeypatch):
65
+ # Both is_contribution_valid and is_rule_valid return True
66
+ contribution = MagicMock()
67
+ contribution.classifier = "c"
68
+ contribution.artefact_name = "a"
69
+ contribution.rule = "r"
70
+ with patch(
71
+ "ara_cli.artefact_scan.is_contribution_valid", return_value=True
72
+ ) as mock_is_contrib, patch(
73
+ "ara_cli.artefact_scan.is_rule_valid", return_value=True
74
+ ) as mock_is_rule:
75
+ result = check_contribution(
76
+ contribution, classified_artefact_info={1: 2}, file_path="p"
77
+ )
78
+ assert result == (True, None)
79
+ mock_is_contrib.assert_called_once_with(contribution, {1: 2})
80
+ mock_is_rule.assert_called_once_with(contribution, {1: 2})
81
+
82
+
83
+ @pytest.mark.parametrize(
84
+ "contribution_attrs,expected",
85
+ [
86
+ (None, True), # contribution is None
87
+ ({"artefact_name": None, "classifier": "foo"}, True), # artefact_name is None
88
+ (
89
+ {"artefact_name": "", "classifier": "foo"},
90
+ True,
91
+ ), # artefact_name is empty string
92
+ ({"artefact_name": "bar", "classifier": None}, True), # classifier is None
93
+ (
94
+ {"artefact_name": "bar", "classifier": ""},
95
+ True,
96
+ ), # classifier is empty string
97
+ ],
98
+ )
99
+ def test_is_rule_valid_short_circuits(contribution_attrs, expected):
100
+ if contribution_attrs is None:
101
+ contribution = None
102
+ else:
103
+ contribution = MagicMock()
104
+ for k, v in contribution_attrs.items():
105
+ setattr(contribution, k, v)
106
+ with patch("ara_cli.artefact_reader.ArtefactReader.read_artefact") as mock_read:
107
+ result = is_rule_valid(contribution, classified_artefact_info={})
108
+ assert result is expected
109
+ mock_read.assert_not_called()
110
+
111
+
112
+ def test_is_rule_valid_rule_is_none():
113
+ """Should return True if contribution.rule is None or falsey."""
114
+ contribution = MagicMock()
115
+ contribution.artefact_name = "foo"
116
+ contribution.classifier = "bar"
117
+ contribution.rule = None
118
+ with patch("ara_cli.artefact_reader.ArtefactReader.read_artefact") as mock_read:
119
+ result = is_rule_valid(contribution, classified_artefact_info={})
120
+ assert result is True
121
+ mock_read.assert_not_called()
122
+
123
+ # Also test rule as empty string
124
+ contribution.rule = ""
125
+ with patch("ara_cli.artefact_reader.ArtefactReader.read_artefact") as mock_read:
126
+ result = is_rule_valid(contribution, classified_artefact_info={})
127
+ assert result is True
128
+ mock_read.assert_not_called()
129
+
130
+
131
+ @pytest.mark.parametrize(
132
+ "parent,expected",
133
+ [
134
+ (None, True), # parent is None
135
+ (MagicMock(rules=None), True), # parent.rules is None
136
+ ],
137
+ )
138
+ def test_is_rule_valid_parent_or_rules_none(parent, expected):
139
+ contribution = MagicMock()
140
+ contribution.artefact_name = "foo"
141
+ contribution.classifier = "bar"
142
+ contribution.rule = "r1"
143
+ with patch(
144
+ "ara_cli.artefact_reader.ArtefactReader.read_artefact", return_value=parent
145
+ ) as mock_read:
146
+ result = is_rule_valid(contribution, classified_artefact_info={})
147
+ assert result is expected
148
+ mock_read.assert_called_once_with("foo", "bar")
149
+
150
+
151
+ def test_is_rule_valid_rule_not_in_parent_rules():
152
+ """Should return False if rule is not in parent.rules."""
153
+ contribution = MagicMock()
154
+ contribution.artefact_name = "foo"
155
+ contribution.classifier = "bar"
156
+ contribution.rule = "missing_rule"
157
+ parent = MagicMock()
158
+ parent.rules = ["rule1", "rule2"]
159
+ with patch(
160
+ "ara_cli.artefact_reader.ArtefactReader.read_artefact", return_value=parent
161
+ ) as mock_read:
162
+ result = is_rule_valid(contribution, classified_artefact_info={})
163
+ assert result is False
164
+ mock_read.assert_called_once_with("foo", "bar")
165
+
166
+
167
+ def test_is_rule_valid_rule_in_parent_rules():
168
+ """Should return True if rule is in parent.rules."""
169
+ contribution = MagicMock()
170
+ contribution.artefact_name = "foo"
171
+ contribution.classifier = "bar"
172
+ contribution.rule = "my_rule"
173
+ parent = MagicMock()
174
+ parent.rules = ["my_rule", "other_rule"]
175
+ with patch(
176
+ "ara_cli.artefact_reader.ArtefactReader.read_artefact", return_value=parent
177
+ ) as mock_read:
178
+ result = is_rule_valid(contribution, classified_artefact_info={})
179
+ assert result is True
180
+ mock_read.assert_called_once_with("foo", "bar")
181
+
182
+
183
+ @pytest.mark.parametrize(
184
+ "contribution_attrs,expected",
185
+ [
186
+ # contribution is None
187
+ (None, True),
188
+ # artefact_name missing/None/empty
189
+ ({"artefact_name": None, "classifier": "foo"}, True),
190
+ ({"artefact_name": "", "classifier": "foo"}, True),
191
+ # classifier missing/None/empty
192
+ ({"artefact_name": "bar", "classifier": None}, True),
193
+ ({"artefact_name": "bar", "classifier": ""}, True),
194
+ ],
195
+ )
196
+ def test_is_contribution_valid_short_circuits(contribution_attrs, expected):
197
+ classified_artefact_info = {"dummy": []}
198
+ if contribution_attrs is None:
199
+ contribution = None
200
+ else:
201
+ contribution = MagicMock()
202
+ for k, v in contribution_attrs.items():
203
+ setattr(contribution, k, v)
204
+ with patch(
205
+ "ara_cli.artefact_fuzzy_search.extract_artefact_names_of_classifier"
206
+ ) as mock_extract:
207
+ result = is_contribution_valid(contribution, classified_artefact_info)
208
+ assert result is expected
209
+ # The extract function should NOT be called in these cases
210
+ mock_extract.assert_not_called()
211
+
212
+
213
+ def test_is_contribution_valid_references_existing_artefact():
214
+ """
215
+ contribution with valid artefact_name and classifier,
216
+ artefact_name IS in list returned by extract_artefact_names_of_classifier.
217
+ """
218
+ contribution = MagicMock()
219
+ contribution.artefact_name = "valid_art"
220
+ contribution.classifier = "valid_clf"
221
+ classified_artefact_info = {"valid_clf": [{"name": "valid_art"}]}
222
+ with patch(
223
+ "ara_cli.artefact_fuzzy_search.extract_artefact_names_of_classifier",
224
+ return_value=["valid_art"],
225
+ ) as mock_extract:
226
+ result = is_contribution_valid(contribution, classified_artefact_info)
227
+ assert result is True
228
+ mock_extract.assert_called_once_with(
229
+ classified_files=classified_artefact_info, classifier="valid_clf"
230
+ )
231
+
232
+
233
+ def test_is_contribution_valid_references_missing_artefact():
234
+ """
235
+ contribution with valid artefact_name and classifier,
236
+ artefact_name is NOT in list returned by extract_artefact_names_of_classifier.
237
+ """
238
+ contribution = MagicMock()
239
+ contribution.artefact_name = "missing_art"
240
+ contribution.classifier = "some_clf"
241
+ classified_artefact_info = {"some_clf": [{"name": "another"}]}
242
+ with patch(
243
+ "ara_cli.artefact_fuzzy_search.extract_artefact_names_of_classifier",
244
+ return_value=["another", "something_else"],
245
+ ) as mock_extract:
246
+ result = is_contribution_valid(contribution, classified_artefact_info)
247
+ assert result is False
248
+ mock_extract.assert_called_once_with(
249
+ classified_files=classified_artefact_info, classifier="some_clf"
250
+ )
5
251
 
6
252
 
7
253
  def test_check_file_valid():
@@ -16,8 +262,10 @@ def test_check_file_valid():
16
262
 
17
263
  with patch("builtins.open", mock_open(read_data="valid content")):
18
264
  is_valid, reason = check_file("dummy_path.feature", mock_artefact_class)
19
-
20
- assert reason is None, f"Reason for invalid found, expected none to be found. The reason found: {reason}"
265
+
266
+ assert (
267
+ reason is None
268
+ ), f"Reason for invalid found, expected none to be found. The reason found: {reason}"
21
269
  assert is_valid is True, "File detected as invalid, expected to be valid"
22
270
 
23
271
 
@@ -51,8 +299,7 @@ def test_check_file_value_error():
51
299
 
52
300
  def test_check_file_assertion_error():
53
301
  mock_artefact_class = MagicMock()
54
- mock_artefact_class.deserialize.side_effect = AssertionError(
55
- "Assertion error")
302
+ mock_artefact_class.deserialize.side_effect = AssertionError("Assertion error")
56
303
 
57
304
  with patch("builtins.open", mock_open(read_data="invalid content")):
58
305
  is_valid, reason = check_file("dummy_path", mock_artefact_class)
@@ -78,6 +325,7 @@ def test_check_file_unexpected_error():
78
325
  assert is_valid is False
79
326
  assert "Unexpected error: Exception('Unexpected error')" in reason
80
327
 
328
+
81
329
  # Tests for find_invalid_files
82
330
 
83
331
 
@@ -86,32 +334,37 @@ def test_find_invalid_files():
86
334
  mock_artefact_class = MagicMock()
87
335
  classified_info = {
88
336
  "test_classifier": [
89
- {"file_path": "file1.txt"}, # Should be checked
90
- {"file_path": "file2.txt"}, # Should be checked
91
- {"file_path": "templates/file3.txt"}, # Should be skipped
92
- {"file_path": "some/path/file.data"} # Should be skipped
337
+ {"file_path": "file1.txt"}, # Should be checked
338
+ {"file_path": "file2.txt"}, # Should be checked
339
+ {"file_path": "templates/file3.txt"}, # Should be skipped
340
+ {"file_path": "some/path/file.data"}, # Should be skipped
93
341
  ]
94
342
  }
95
-
96
- with patch("ara_cli.artefact_models.artefact_mapping.artefact_type_mapping",
97
- {"test_classifier": mock_artefact_class}):
343
+
344
+ with patch(
345
+ "ara_cli.artefact_models.artefact_mapping.artefact_type_mapping",
346
+ {"test_classifier": mock_artefact_class},
347
+ ):
98
348
  with patch("ara_cli.artefact_scan.check_file") as mock_check_file:
99
349
  mock_check_file.side_effect = [
100
- (True, None), # for file1.txt
101
- (False, "Invalid content") # for file2.txt
350
+ (True, None), # for file1.txt
351
+ (False, "Invalid content"), # for file2.txt
102
352
  ]
103
353
 
104
354
  invalid_files = find_invalid_files(classified_info, "test_classifier")
105
-
355
+
106
356
  assert len(invalid_files) == 1
107
357
  assert invalid_files[0] == ("file2.txt", "Invalid content")
108
358
  assert mock_check_file.call_count == 2
109
-
359
+
110
360
  # Check that check_file was called with the correct parameters
111
- mock_check_file.assert_has_calls([
112
- call("file1.txt", mock_artefact_class, classified_info),
113
- call("file2.txt", mock_artefact_class, classified_info)
114
- ], any_order=False)
361
+ mock_check_file.assert_has_calls(
362
+ [
363
+ call("file1.txt", mock_artefact_class, classified_info),
364
+ call("file2.txt", mock_artefact_class, classified_info),
365
+ ],
366
+ any_order=False,
367
+ )
115
368
 
116
369
 
117
370
  def test_show_results_no_issues(capsys):
@@ -120,18 +373,20 @@ def test_show_results_no_issues(capsys):
120
373
  show_results(invalid_artefacts)
121
374
  captured = capsys.readouterr()
122
375
  assert captured.out == "All files are good!\n"
123
- m.assert_called_once_with("incompatible_artefacts_report.md", "w", encoding="utf-8")
376
+ m.assert_called_once_with(
377
+ "incompatible_artefacts_report.md", "w", encoding="utf-8"
378
+ )
124
379
  handle = m()
125
- handle.write.assert_has_calls([
126
- call("# Artefact Check Report\n\n"),
127
- call("No problems found.\n")
128
- ], any_order=False)
380
+ handle.write.assert_has_calls(
381
+ [call("# Artefact Check Report\n\n"), call("No problems found.\n")],
382
+ any_order=False,
383
+ )
129
384
 
130
385
 
131
386
  def test_show_results_with_issues(capsys):
132
387
  invalid_artefacts = {
133
388
  "classifier1": [("file1.txt", "reason1"), ("file2.txt", "reason2")],
134
- "classifier2": [("file3.txt", "reason3")]
389
+ "classifier2": [("file3.txt", "reason3")],
135
390
  }
136
391
  with patch("builtins.open", mock_open()) as m:
137
392
  show_results(invalid_artefacts)
@@ -147,7 +402,9 @@ def test_show_results_with_issues(capsys):
147
402
  "\t\treason3\n"
148
403
  )
149
404
  assert captured.out == expected_output
150
- m.assert_called_once_with("incompatible_artefacts_report.md", "w", encoding="utf-8")
405
+ m.assert_called_once_with(
406
+ "incompatible_artefacts_report.md", "w", encoding="utf-8"
407
+ )
151
408
  handle = m()
152
409
  expected_writes = [
153
410
  call("# Artefact Check Report\n\n"),
@@ -157,7 +414,7 @@ def test_show_results_with_issues(capsys):
157
414
  call("\n"),
158
415
  call("## classifier2\n"),
159
416
  call("- `file3.txt`: reason3\n"),
160
- call("\n")
417
+ call("\n"),
161
418
  ]
162
419
  handle.write.assert_has_calls(expected_writes, any_order=False)
163
420
 
@@ -166,7 +423,7 @@ def test_check_file_with_invalid_contribution():
166
423
  """Tests file with invalid contribution reference."""
167
424
  mock_artefact_instance = MagicMock()
168
425
  mock_artefact_instance.title = "dummy_path"
169
-
426
+
170
427
  # Set up invalid contribution
171
428
  mock_contribution = MagicMock()
172
429
  mock_contribution.classifier = "test_classifier"
@@ -178,12 +435,16 @@ def test_check_file_with_invalid_contribution():
178
435
 
179
436
  # Mock classified_artefact_info
180
437
  classified_info = {"test_classifier": [{"name": "existing_artefact"}]}
181
-
438
+
182
439
  # Mock extract_artefact_names_of_classifier to return a list without the referenced artefact
183
440
  with patch("builtins.open", mock_open(read_data="valid content")):
184
- with patch("ara_cli.artefact_fuzzy_search.extract_artefact_names_of_classifier",
185
- return_value=["existing_artefact"]):
186
- is_valid, reason = check_file("dummy_path.feature", mock_artefact_class, classified_info)
187
-
441
+ with patch(
442
+ "ara_cli.artefact_fuzzy_search.extract_artefact_names_of_classifier",
443
+ return_value=["existing_artefact"],
444
+ ):
445
+ is_valid, reason = check_file(
446
+ "dummy_path.feature", mock_artefact_class, classified_info
447
+ )
448
+
188
449
  assert is_valid is False
189
450
  assert "Invalid Contribution Reference" in reason
tests/test_chat.py CHANGED
@@ -13,8 +13,8 @@ from ara_cli.ara_config import ConfigManager
13
13
  def get_default_config():
14
14
  return SimpleNamespace(
15
15
  ext_code_dirs=[
16
- {"source_dir_1": "./src"},
17
- {"source_dir_2": "./tests"},
16
+ {"source_dir": "./src"},
17
+ {"source_dir": "./tests"},
18
18
  ],
19
19
  glossary_dir="./glossary",
20
20
  doc_dir="./docs",
@@ -1052,19 +1052,39 @@ def test_do_SEND(temp_chat_file):
1052
1052
  mock_send_message.assert_called_once()
1053
1053
 
1054
1054
 
1055
- def test_do_LOAD_TEMPLATE(temp_chat_file):
1056
- mock_config = get_default_config()
1055
+ @pytest.mark.parametrize("template_name, artefact_obj, expected_write, expected_print", [
1056
+ ("TestTemplate", MagicMock(serialize=MagicMock(return_value="serialized_content")), "serialized_content", "Loaded TestTemplate artefact template\n"),
1057
+ ("AnotherTemplate", MagicMock(serialize=MagicMock(return_value="other_content")), "other_content", "Loaded AnotherTemplate artefact template\n"),
1058
+ ])
1059
+ def test_do_LOAD_TEMPLATE_success(temp_chat_file, template_name, artefact_obj, expected_write, expected_print, capsys):
1060
+ mock_config = MagicMock() # or use get_default_config() if needed
1057
1061
  with patch('ara_cli.prompt_handler.ConfigManager.get_config', return_value=mock_config):
1058
1062
  chat = Chat(temp_chat_file.name, reset=False)
1059
- template_name = 'test_template'
1060
-
1061
- module_path = os.path.abspath(os.path.dirname(ara_cli.__file__))
1062
- directory = f'{module_path}/templates'
1063
- pattern = f"template.{template_name}"
1064
- file_type = "template"
1065
- exclude_pattern = os.path.join(directory, "template.*.prompt_log.md")
1066
-
1067
- with patch.object(chat, '_load_helper') as mock_load_helper:
1063
+ # Patch the artefact loader to return artefact_obj
1064
+ with patch('ara_cli.artefact_models.artefact_templates.template_artefact_of_type', return_value=artefact_obj) as mock_template_loader, \
1065
+ patch.object(chat, 'add_prompt_tag_if_needed') as mock_add_prompt_tag, \
1066
+ patch("builtins.open", mock_open()) as mock_file:
1068
1067
  chat.do_LOAD_TEMPLATE(template_name)
1069
-
1070
- mock_load_helper.assert_called_once_with(directory, pattern, file_type, exclude_pattern)
1068
+ mock_template_loader.assert_called_once_with(template_name)
1069
+ artefact_obj.serialize.assert_called_once_with()
1070
+ mock_add_prompt_tag.assert_called_once_with(chat.chat_name)
1071
+ mock_file.assert_called_with(chat.chat_name, 'a', encoding='utf-8')
1072
+ mock_file().write.assert_called_once_with(expected_write)
1073
+ out = capsys.readouterr()
1074
+ assert expected_print in out.out
1075
+
1076
+ @pytest.mark.parametrize("template_name", [
1077
+ ("MissingTemplate"),
1078
+ (""),
1079
+ ])
1080
+ def test_do_LOAD_TEMPLATE_missing_artefact(temp_chat_file, template_name):
1081
+ mock_config = MagicMock()
1082
+ with patch('ara_cli.prompt_handler.ConfigManager.get_config', return_value=mock_config):
1083
+ chat = Chat(temp_chat_file.name, reset=False)
1084
+ with patch('ara_cli.artefact_models.artefact_templates.template_artefact_of_type', return_value=None) as mock_template_loader, \
1085
+ patch.object(chat, 'add_prompt_tag_if_needed') as mock_add_prompt_tag, \
1086
+ patch("builtins.open", mock_open()) as mock_file:
1087
+ chat.do_LOAD_TEMPLATE(template_name)
1088
+ mock_template_loader.assert_called_once_with(template_name)
1089
+ mock_add_prompt_tag.assert_not_called()
1090
+ mock_file.assert_not_called()
@@ -1,10 +0,0 @@
1
- @sample_tag
2
- Businessgoal: <descriptive title>
3
-
4
- Contributes to <filename or title of the artefact> <agile requirement artefact category> <(optional in case the contribution is to an artefact that is detailed with rules) using rule <rule as it is formulated>
5
-
6
- In order to <reach primarily a monetary business goal>
7
- As a <business related role>
8
- I want <something that helps me to reach my monetary goal>
9
-
10
- Description: <further optional description to understand the business goal, markdown capable text formatting>
@@ -1,10 +0,0 @@
1
- @sample_tag
2
- Capability: <descriptive title>
3
-
4
- Contributes to <filename or title of the artefact> <agile requirement artefact category> <(optional in case the contribution is to an artefact that is detailed with rules) using rule <rule as it is formulated>
5
-
6
- To be able to <needed capability for stakeholders that are the
7
- enablers/relevant for reaching the business goal>
8
-
9
- Description: <further optional description to understand
10
- the capability, markdown capable text formatting>
@@ -1,15 +0,0 @@
1
- @sample_tag
2
- Epic: <descriptive title>
3
-
4
- Contributes to <filename or title of the artefact> <agile requirement artefact category> <(optional in case the contribution is to an artefact that is detailed with rules) using rule <rule as it is formulated>
5
-
6
- In order to <achieve a benefit>
7
- As a <(user) role>
8
- I want <a certain product behavior>
9
-
10
- Rule: <rule needed to fulfill the wanted product behavior>
11
- Rule: <rule needed to fulfill the wanted product behavior>
12
- Rule: <rule needed to fulfill the wanted product behavior>
13
-
14
- Description: <further optional description to understand
15
- the epic, markdown capable text formatting>
@@ -1,6 +0,0 @@
1
- @sample_tag
2
- Example: <descriptive title>
3
-
4
- Illustrates <filename or title of the artefact> <agile requirement artefact category> <(optional in case the contribution is to an artefact that is detailed with rules) using rule <rule as it is formulated>
5
-
6
- Description: <further optional description to understand the rule, no format defined, the example artefact is only a placeholder>
@@ -1,26 +0,0 @@
1
- @sample_tag
2
- Feature: <descriptive title>
3
-
4
- As a <user>
5
- I want to <do something | need something>
6
- So that <I can achieve something>
7
-
8
- Contributes to <filename or title of the artefact> <agile requirement artefact category> <(optional in case the contribution is to an artefact that is detailed with rules) using rule <rule as it is formulated>
9
-
10
- Description: <further optional description to understand
11
- the rule, no format defined, the example artefact is only a placeholder>
12
-
13
- Scenario: <descriptive scenario title>
14
- Given <precondition>
15
- When <action>
16
- Then <expected result>
17
-
18
- Scenario Outline: <descriptive scenario title>
19
- Given <precondition>
20
- When <action>
21
- Then <expected result>
22
-
23
- Examples:
24
- | descriptive scenario title | precondition | action | expected result |
25
- | <example title 1> | <example precond. 1> | <example action 1> | <example result 1> |
26
- | <example title 2> | <example precond. 2> | <example action 2> | <example result 2> |
@@ -1,14 +0,0 @@
1
- @sample_tag
2
- Issue: <descriptive issue>
3
-
4
- Contributes to <filename or title of the artefact> <agile requirement artefact category> <(optional in case the contribution is to an artefact that is detailed with rules) using rule <rule as it is formulated> | blank | filled with text that does not refer to an artefact or rule (then this a free issue)
5
-
6
- *Optional descriptions of the issue in Gherkin style*
7
-
8
- Given <descriptive text of the starting conditions where the issue occurs>
9
- When <action under which the issues occurs>
10
- Then <resulting behavior in contrast to the expected behavior>
11
-
12
- *or optional free text description*
13
-
14
- Description: <further free text description to understand the issue, no format defined>
@@ -1,15 +0,0 @@
1
- @sample_tag
2
- Keyfeature: <descriptive title>
3
-
4
- Contributes to <filename or title of the artefact> <agile requirement artefact category> <(optional in case the contribution is to an artefact that is detailed with rules) using rule <rule as it is formulated>
5
-
6
- In order to <support a capability or business goal>
7
- As a <main stakeholder who will benefit>
8
- I want <a product feature that helps me doing something so that I can achieve my named goal>
9
-
10
- Description: <further optional description to understand the capability, markdown capable text formatting, best practice is using
11
- GIVEN any precondition
12
- AND another precondition
13
- WHEN some action takes place
14
- THEN some result is to be expected
15
- AND some other result is to be expected>
@@ -1,6 +0,0 @@
1
- @to-do
2
- Task: <descriptive title>
3
-
4
- Contributes to <filename or title of the artefact> <agile requirement artefact category> <(optional in case the contribution is to an artefact that is detailed with rules) using rule <rule as it is formulated> | blank | filled with text that does not refer to an artefact or rule (then this is a free task)
5
-
6
- Description: <further optional description to understand the task, no format defined>
@@ -1,17 +0,0 @@
1
- @sample_tag
2
- Userstory: <descriptive title>
3
-
4
- Contributes to <filename or title of the artefact> <agile requirement artefact category> <(optional in case the contribution is to an artefact that is detailed with rules) using rule <rule as it is formulated>
5
-
6
- Estimate: <story points, scale?>
7
-
8
- In order to <achieve a benefit>
9
- As a <(user) role>
10
- I want <a certain product behavior>
11
-
12
- Rule: <rule needed to fulfill the wanted product behavior>
13
- Rule: <rule needed to fulfill the wanted product behavior>
14
- Rule: <rule needed to fulfill the wanted product behavior>
15
-
16
- Description: <further optional description to understand
17
- the user story, markdown capable text formatting>
@@ -1,14 +0,0 @@
1
- @sample_tag
2
- Vision: <descriptive title>
3
-
4
- Contributes to <filename or title of the artefact> <agile requirement artefact category> <(optional in case the contribution is to an artefact that is detailed with rules) using rule <rule as it is formulated>
5
-
6
- For <target customer>
7
- Who <needs something>
8
- The <product name> is a <product category>
9
- That <key benefit, compelling reason to buy>
10
- Unlike <primary competitive alternative>
11
- Our product <statement of primary differentiation>
12
-
13
- Description: <further optional description to understand
14
- the vision, markdown capable text formatting>