|
1 | | -from unittest.mock import MagicMock, patch |
| 1 | +from unittest.mock import MagicMock, call, patch |
2 | 2 |
|
3 | 3 | import pytest |
4 | 4 | from openwisp_utils.releaser.release import check_prerequisites |
@@ -155,26 +155,86 @@ def test_main_flow_pr_merge_wait(mock_all): |
155 | 155 | @patch("openwisp_utils.releaser.release.update_changelog_file") |
156 | 156 | @patch("openwisp_utils.releaser.release.format_file_with_docstrfmt") |
157 | 157 | @patch("openwisp_utils.releaser.release.subprocess.run") |
| 158 | +@patch("openwisp_utils.releaser.release.branch_exists") |
158 | 159 | @patch("openwisp_utils.releaser.release.questionary") |
159 | 160 | def test_port_changelog_to_main_flow( |
160 | | - mock_questionary, mock_subprocess, mock_format_file, mock_update_changelog |
| 161 | + mock_questionary, |
| 162 | + mock_branch_exists, |
| 163 | + mock_subprocess, |
| 164 | + mock_format_file, |
| 165 | + mock_update_changelog, |
161 | 166 | ): |
162 | 167 | """Tests the changelog porting process for both RST and MD files, and the cancellation path.""" |
163 | 168 | mock_gh = MagicMock() |
164 | 169 | mock_config_rst = {"changelog_path": "CHANGES.rst"} |
| 170 | + # Both branches exist: user is asked |
| 171 | + mock_branch_exists.return_value = True |
165 | 172 | mock_questionary.select.return_value.ask.return_value = "main" |
166 | 173 | port_changelog_to_main(mock_gh, mock_config_rst, "1.1.1", "- fix", "1.1.x") |
167 | 174 | mock_gh.create_pr.assert_called_once() |
168 | 175 | mock_format_file.assert_called_once_with("CHANGES.rst") |
169 | 176 |
|
170 | 177 | mock_gh.reset_mock() |
171 | 178 |
|
172 | | - # Test Cancellation path |
| 179 | + # Test Cancellation path (when both branches exist and user cancels) |
173 | 180 | mock_questionary.select.return_value.ask.return_value = None |
174 | 181 | port_changelog_to_main(mock_gh, mock_config_rst, "1.1.1", "- fix", "1.1.x") |
175 | 182 | mock_gh.create_pr.assert_not_called() |
176 | 183 |
|
177 | 184 |
|
| 185 | +@patch("openwisp_utils.releaser.release.update_changelog_file") |
| 186 | +@patch("openwisp_utils.releaser.release.subprocess.run") |
| 187 | +@patch("openwisp_utils.releaser.release.branch_exists") |
| 188 | +def test_port_changelog_only_master_exists( |
| 189 | + mock_branch_exists, mock_subprocess, mock_update_changelog |
| 190 | +): |
| 191 | + """`master` is auto-selected when `main` does not exist locally.""" |
| 192 | + mock_gh = MagicMock() |
| 193 | + mock_config = {"changelog_path": "CHANGES.rst"} |
| 194 | + # Simulate: main=False, master=True |
| 195 | + mock_branch_exists.side_effect = lambda name: name == "master" |
| 196 | + port_changelog_to_main(mock_gh, mock_config, "1.1.1", "- fix", "1.1.x") |
| 197 | + mock_gh.create_pr.assert_called_once() |
| 198 | + # Verify PR was opened against master |
| 199 | + assert mock_gh.create_pr.call_args[0][1] == "master" |
| 200 | + |
| 201 | + |
| 202 | +@patch("openwisp_utils.releaser.release.update_changelog_file") |
| 203 | +@patch("openwisp_utils.releaser.release.subprocess.run") |
| 204 | +@patch("openwisp_utils.releaser.release.branch_exists") |
| 205 | +def test_port_changelog_only_main_exists( |
| 206 | + mock_branch_exists, mock_subprocess, mock_update_changelog |
| 207 | +): |
| 208 | + """`main` is auto-selected when it exists and `master` does not.""" |
| 209 | + mock_gh = MagicMock() |
| 210 | + mock_config = {"changelog_path": "CHANGES.rst"} |
| 211 | + # Simulate: main=True, master=False |
| 212 | + mock_branch_exists.side_effect = lambda name: name == "main" |
| 213 | + port_changelog_to_main(mock_gh, mock_config, "1.1.1", "- fix", "1.1.x") |
| 214 | + mock_gh.create_pr.assert_called_once() |
| 215 | + # Verify PR was opened against main |
| 216 | + assert mock_gh.create_pr.call_args[0][1] == "main" |
| 217 | + |
| 218 | + |
| 219 | +@patch("openwisp_utils.releaser.release.update_changelog_file") |
| 220 | +@patch("openwisp_utils.releaser.release.subprocess.run") |
| 221 | +@patch("openwisp_utils.releaser.release.branch_exists") |
| 222 | +@patch("openwisp_utils.releaser.release.questionary") |
| 223 | +def test_port_changelog_both_branches_prompts_user( |
| 224 | + mock_questionary, mock_branch_exists, mock_subprocess, mock_update_changelog |
| 225 | +): |
| 226 | + """User is prompted to choose when both `main` and `master` exist.""" |
| 227 | + mock_gh = MagicMock() |
| 228 | + mock_config = {"changelog_path": "CHANGES.rst"} |
| 229 | + # Both branches exist |
| 230 | + mock_branch_exists.return_value = True |
| 231 | + mock_questionary.select.return_value.ask.return_value = "master" |
| 232 | + port_changelog_to_main(mock_gh, mock_config, "1.1.1", "- fix", "1.1.x") |
| 233 | + mock_questionary.select.assert_called_once() |
| 234 | + mock_gh.create_pr.assert_called_once() |
| 235 | + assert mock_gh.create_pr.call_args[0][1] == "master" |
| 236 | + |
| 237 | + |
178 | 238 | def test_main_bugfix_flow_with_porting(mock_all, mocker): |
179 | 239 | """Tests the main release flow for a bugfix, including accepting the changelog port.""" |
180 | 240 | mock_all["_git_command_map"][ |
|
0 commit comments