|
| 1 | +import pytest |
| 2 | +from apps.jira_utils.jira_information import ( |
| 3 | + get_jira_information, |
| 4 | + process_jira_command_line_config_file, |
| 5 | + get_jira_ids_from_file_content, |
| 6 | +) |
| 7 | +from simple_logger.logger import get_logger |
| 8 | +from pyhelper_utils.shell import run_command |
| 9 | +import shlex |
| 10 | +import subprocess |
| 11 | +import os |
| 12 | + |
| 13 | +LOGGER = get_logger(name=__name__) |
| 14 | +BASE_COMMAND = "poetry run python apps/jira_utils/jira_information.py --verbose " |
| 15 | + |
| 16 | + |
| 17 | +def test_process_jira_command_line_config_file_empty_config_token() -> None: |
| 18 | + config_file = os.path.join(os.path.dirname(__file__), "test_jira_cfg_file.yaml") |
| 19 | + rc, _, err = run_command( |
| 20 | + command=shlex.split(f"{BASE_COMMAND} --config-file-path {config_file}"), |
| 21 | + verify_stderr=False, |
| 22 | + check=False, |
| 23 | + capture_output=False, |
| 24 | + stderr=subprocess.PIPE, |
| 25 | + ) |
| 26 | + assert "Jira url and token are required." in err |
| 27 | + assert not rc |
| 28 | + |
| 29 | + |
| 30 | +def test_process_jira_command_line_config_file_valid_config(mocker): |
| 31 | + config_file_path = "/path/to/config" |
| 32 | + url = "https://example.com" |
| 33 | + token = "1234567890" |
| 34 | + issue_pattern = "*" |
| 35 | + resolved_statuses = ["RESOLVED"] |
| 36 | + version_string_not_targeted_jiras = "v1.*" |
| 37 | + target_versions = ["v2", "v3"] |
| 38 | + skip_projects = [1, 2] |
| 39 | + mock_get_util_config = mocker.patch( |
| 40 | + "apps.jira_utils.jira_information.get_util_config", |
| 41 | + return_value={ |
| 42 | + "url": url, |
| 43 | + "token": token, |
| 44 | + "issue_pattern": "*", |
| 45 | + "resolved_statuses": ["RESOLVED"], |
| 46 | + "version_string_not_targeted_jiras": version_string_not_targeted_jiras, |
| 47 | + "target_versions": target_versions, |
| 48 | + "skip_project_ids": skip_projects, |
| 49 | + }, |
| 50 | + ) |
| 51 | + result = process_jira_command_line_config_file( |
| 52 | + config_file_path, |
| 53 | + url, |
| 54 | + token, |
| 55 | + issue_pattern, |
| 56 | + resolved_statuses, |
| 57 | + version_string_not_targeted_jiras, |
| 58 | + target_versions, |
| 59 | + skip_projects, |
| 60 | + ) |
| 61 | + assert result == { |
| 62 | + "url": url, |
| 63 | + "token": token, |
| 64 | + "issue_pattern": issue_pattern, |
| 65 | + "resolved_status": resolved_statuses, |
| 66 | + "not_targeted_version_str": version_string_not_targeted_jiras, |
| 67 | + "target_versions": target_versions, |
| 68 | + "skip_project_ids": skip_projects, |
| 69 | + } |
| 70 | + mock_get_util_config.assert_called_once() |
| 71 | + |
| 72 | + |
| 73 | +@pytest.mark.parametrize( |
| 74 | + "jira_id, resolved_status, jira_target_versions, target_version_str, file_name, " |
| 75 | + "skip_project_ids, expected_jira_error_string, " |
| 76 | + "test_jira_version", |
| 77 | + [ |
| 78 | + # Test case 1: Issue with no jira target versions and not resolved status |
| 79 | + ("issue1", ["resolved"], [], "1.0", "file1.txt", [], "", "1.0"), |
| 80 | + # Test case 2: Issue with no jira target versions, but resolved status |
| 81 | + ("issue2", ["open"], [], "1.0", "file2.txt", [], "issue2 current status: open is resolved.", "1.0"), |
| 82 | + # Test case 3: Issue with no jira target versions, default resolved status |
| 83 | + ("issue3", [], [], "", "file3.txt", [], "", "1.1"), |
| 84 | + # Test case 4: Issue with not resolved state, but matching jira target version |
| 85 | + ("issue4", ["resolved"], ["1.0"], "1.0", "file4.txt", [], "", "1.0"), |
| 86 | + # Test case 5: Issue with not resolved state, and not matching jira target version |
| 87 | + ( |
| 88 | + "issue5", |
| 89 | + ["resolved"], |
| 90 | + ["1.1"], |
| 91 | + "1.0", |
| 92 | + "file5.txt", |
| 93 | + [], |
| 94 | + "issue5 target version: 1.0, does not match expected version ['1.1'].", |
| 95 | + "1.0", |
| 96 | + ), |
| 97 | + # Test case 6: Issue that would be skipped for version check because of skip |
| 98 | + ("issue6", ["resolved"], ["1.0"], "1.0", "file6.txt", ["issue"], "", "1.1"), |
| 99 | + # Test case 7: Issue that would be skipped for version check but fail resolved check |
| 100 | + ("issue7", ["open"], ["1.0"], "1.0", "file6.txt", ["issue"], "issue7 current status: open is resolved.", "1.1"), |
| 101 | + ], |
| 102 | + ids=[ |
| 103 | + "test_no_jira_versions_no_resolved_status", |
| 104 | + "test_no_jira_versions_resolved_status", |
| 105 | + "test_no_jira_versions_default_resolved_status", |
| 106 | + "test_matching_target_versions", |
| 107 | + "test_no_target_versions_not_resolved_state", |
| 108 | + "test_skip_version_check", |
| 109 | + "test_skip_version_check_fail_status_check", |
| 110 | + ], |
| 111 | +) |
| 112 | +def test_get_jira_information( |
| 113 | + mocker, |
| 114 | + jira_id, |
| 115 | + resolved_status, |
| 116 | + jira_target_versions, |
| 117 | + target_version_str, |
| 118 | + file_name, |
| 119 | + skip_project_ids, |
| 120 | + expected_jira_error_string, |
| 121 | + test_jira_version, |
| 122 | +): |
| 123 | + mock_jira = mocker.MagicMock() |
| 124 | + mock_jira.fields.status.name = "open" |
| 125 | + jira_version = mocker.MagicMock() |
| 126 | + jira_version.name = test_jira_version |
| 127 | + mock_jira.fixVersions = [jira_version] |
| 128 | + mocker.patch("apps.jira_utils.jira_information.get_issue", return_value=mock_jira) |
| 129 | + |
| 130 | + if jira_target_versions: |
| 131 | + mocker.patch( |
| 132 | + "apps.jira_utils.jira_information.re.search", |
| 133 | + return_value=mocker.MagicMock(group=lambda x: test_jira_version), |
| 134 | + ) |
| 135 | + result = get_jira_information( |
| 136 | + jira_object=mock_jira, |
| 137 | + jira_id=jira_id, |
| 138 | + resolved_status=resolved_status, |
| 139 | + target_version_str="1.0", |
| 140 | + skip_project_ids=skip_project_ids, |
| 141 | + jira_target_versions=jira_target_versions, |
| 142 | + file_name=file_name, |
| 143 | + ) |
| 144 | + else: |
| 145 | + result = get_jira_information( |
| 146 | + jira_object=mock_jira, |
| 147 | + jira_id=jira_id, |
| 148 | + resolved_status=resolved_status, |
| 149 | + target_version_str="1.0", |
| 150 | + skip_project_ids=skip_project_ids, |
| 151 | + jira_target_versions=jira_target_versions, |
| 152 | + file_name=file_name, |
| 153 | + ) |
| 154 | + |
| 155 | + assert result == (file_name, expected_jira_error_string) |
| 156 | + |
| 157 | + |
| 158 | +@pytest.mark.parametrize( |
| 159 | + "content_and_expected", |
| 160 | + [ |
| 161 | + pytest.param({"content": "pytest.mark.jira(ABC-1111)", "expected": {"ABC-1111"}}, id="pytest_mark_jira"), |
| 162 | + pytest.param({"content": "JIRA ID is jira_id=ABC-1111", "expected": {"ABC-1111"}}, id="jira_id="), |
| 163 | + pytest.param( |
| 164 | + {"content": "JIRA URL is https://example.com/browse/ABC-1111", "expected": {"ABC-1111"}}, id="jira_url=" |
| 165 | + ), |
| 166 | + pytest.param( |
| 167 | + { |
| 168 | + "content": "pytest.mark.jira(ABC-1111)\nJIRA ID is jira_id=ABC-1112\nJIRA URL is https://example.com/browse/ABC-1113", |
| 169 | + "expected": {"ABC-1111", "ABC-1112", "ABC-1113"}, |
| 170 | + }, |
| 171 | + id="multiple_jira", |
| 172 | + ), |
| 173 | + pytest.param( |
| 174 | + { |
| 175 | + "content": "pytest.mark.jira(ABC-1111)\nJIRA ID is jira_id=ABC-1111\nJIRA URL is https://example.com/browse/ABC-1111", |
| 176 | + "expected": {"ABC-1111"}, |
| 177 | + }, |
| 178 | + id="multiple_jira_same_ids", |
| 179 | + ), |
| 180 | + pytest.param({"content": "No Jiera", "expected": set()}, id="no_jira"), |
| 181 | + ], |
| 182 | +) |
| 183 | +def test_get_jira_ids_from_file_content(content_and_expected): |
| 184 | + jira_ids = get_jira_ids_from_file_content( |
| 185 | + file_content=content_and_expected["content"], issue_pattern=r"([A-Z]+-[0-9]+)", jira_url="https://example.com" |
| 186 | + ) |
| 187 | + assert jira_ids == content_and_expected["expected"] |
0 commit comments