Skip to content

Commit 66e6e57

Browse files
added test cases
1 parent 7303acc commit 66e6e57

3 files changed

Lines changed: 135 additions & 0 deletions

File tree

fedmsg.d/sync2jira.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@
9595
'upstream_id', # Add comment with upstream PR link on create
9696
'url', # Include upstream URL in description
9797
'github_project_fields', # Sync storypoints & priority from GitHub Projects
98+
{'fixVersion': {'overwrite': False}}, # Sync milestone as fixVersion
99+
{'transition': 'Closed'}, # Transition Jira when upstream issue closes
98100
{'merge_transition': 'Closed'}, # Transition Jira when PR is merged
99101
{'link_transition': 'In Progress'}, # Transition Jira when PR is first linked
100102
{'assignee': {'overwrite': False}}, # Sync assignee (don't overwrite existing)

tests/test_downstream_issue.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,14 @@ def test_maybe_convert_markdown(self, mock_convert):
11231123
d.maybe_convert_markdown(issue)
11241124
self.assertEqual(issue.content, "h1. Hello")
11251125

1126+
# Converts with explicit "issue_updates" parameter
1127+
mock_convert.reset_mock()
1128+
mock_convert.return_value = "h1. Hello"
1129+
issue.downstream = {"issue_updates": ["github_markdown"]}
1130+
issue.content = "# Hello"
1131+
d.maybe_convert_markdown(issue, "issue_updates")
1132+
self.assertEqual(issue.content, "h1. Hello")
1133+
11261134
# Works with pr_updates key
11271135
mock_convert.reset_mock()
11281136
mock_convert.return_value = "*bold*"
@@ -1146,11 +1154,29 @@ def test_maybe_convert_markdown(self, mock_convert):
11461154
self.assertEqual(issue.content, "")
11471155

11481156
# Skips when source is not github
1157+
mock_convert.reset_mock()
11491158
issue.source = "pagure"
11501159
issue.downstream = {"issue_updates": ["github_markdown"]}
11511160
issue.content = "# Hello"
11521161
d.maybe_convert_markdown(issue)
11531162
self.assertEqual(issue.content, "# Hello")
1163+
self.assertEqual(mock_convert.call_count, 0)
1164+
1165+
# Skips when updates_key is not present in downstream config
1166+
mock_convert.reset_mock()
1167+
issue.source = "github"
1168+
issue.downstream = {}
1169+
issue.content = "# Hello"
1170+
d.maybe_convert_markdown(issue)
1171+
self.assertEqual(issue.content, "# Hello")
1172+
self.assertEqual(mock_convert.call_count, 0)
1173+
1174+
# Skips when updates list is empty
1175+
issue.downstream = {"issue_updates": []}
1176+
issue.content = "# Hello"
1177+
d.maybe_convert_markdown(issue)
1178+
self.assertEqual(issue.content, "# Hello")
1179+
self.assertEqual(mock_convert.call_count, 0)
11541180

11551181
@mock.patch(PATH + "pypandoc")
11561182
def test_convert_content(self, mock_pypandoc):

tests/test_downstream_pr.py

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import unittest.mock as mock
33
from unittest.mock import MagicMock
44

5+
import sync2jira.downstream_issue as d_issue
56
import sync2jira.downstream_pr as d
67

78
PATH = "sync2jira.downstream_pr."
@@ -397,6 +398,112 @@ def test_update_pr_transition(self, mock_d_issue):
397398
mock_client, self.mock_existing, "CUSTOM_TRANSITION1", self.mock_pr
398399
)
399400

401+
@mock.patch(PATH + "d_issue.change_status")
402+
@mock.patch(PATH + "d_issue.update_jira_issue", wraps=d_issue.update_jira_issue)
403+
@mock.patch(PATH + "comment_exists", return_value=True)
404+
@mock.patch(PATH + "format_comment", return_value="mock_comment")
405+
@mock.patch(PATH + "d_issue.attach_link")
406+
@mock.patch(PATH + "issue_link_exists", return_value=True)
407+
def test_update_jira_issue_transition_noop_when_status_none(
408+
self,
409+
mock_issue_link_exists,
410+
mock_attach_link,
411+
mock_format_comment,
412+
mock_comment_exists,
413+
mock_shared_update,
414+
mock_change_status,
415+
):
416+
"""github.pull_request path: PR has status=None, so _update_transition
417+
is a no-op even when {'transition': 'Closed'} is in pr_updates.
418+
"""
419+
self.mock_pr.status = None
420+
self.mock_pr.downstream = {
421+
"pr_updates": [{"transition": "Closed"}],
422+
}
423+
424+
d.update_jira_issue(
425+
self.mock_existing, self.mock_pr, self.mock_client, self.mock_config
426+
)
427+
428+
mock_change_status.assert_not_called()
429+
430+
@mock.patch(PATH + "d_issue.change_status")
431+
@mock.patch(PATH + "comment_exists", return_value=True)
432+
@mock.patch(PATH + "format_comment", return_value="mock_comment")
433+
@mock.patch(PATH + "d_issue.attach_link")
434+
@mock.patch(PATH + "issue_link_exists", return_value=True)
435+
def test_update_jira_issue_merged_pr_no_duplicate_transition(
436+
self,
437+
mock_issue_link_exists,
438+
mock_attach_link,
439+
mock_format_comment,
440+
mock_comment_exists,
441+
mock_change_status,
442+
):
443+
"""github.issues path: merged PR with status='Closed'.
444+
445+
merge_transition fires first (via _update_pr_transitions), then
446+
_update_transition finds Jira already in target state and skips.
447+
change_status is called once (for merge_transition) not twice.
448+
"""
449+
self.mock_pr.suffix = "merged"
450+
self.mock_pr.status = "Closed"
451+
self.mock_pr.downstream = {
452+
"pr_updates": [
453+
{"merge_transition": "Closed"},
454+
{"transition": "Closed"},
455+
],
456+
}
457+
self.mock_existing.fields.status.name = "Closed"
458+
459+
d.update_jira_issue(
460+
self.mock_existing, self.mock_pr, self.mock_client, self.mock_config
461+
)
462+
463+
# merge_transition fires via _update_pr_transition
464+
mock_change_status.assert_called_once_with(
465+
self.mock_client, self.mock_existing, "Closed", self.mock_pr
466+
)
467+
468+
@mock.patch(PATH + "d_issue.change_status")
469+
@mock.patch(PATH + "comment_exists", return_value=True)
470+
@mock.patch(PATH + "format_comment", return_value="mock_comment")
471+
@mock.patch(PATH + "d_issue.attach_link")
472+
@mock.patch(PATH + "issue_link_exists", return_value=True)
473+
def test_update_jira_issue_closed_without_merge_transitions(
474+
self,
475+
mock_issue_link_exists,
476+
mock_attach_link,
477+
mock_format_comment,
478+
mock_comment_exists,
479+
mock_change_status,
480+
):
481+
"""github.issues path: PR closed without merge, status='Closed'.
482+
483+
merge_transition skips (suffix is 'closed', not 'merged').
484+
_update_transition sees status=='Closed' and fires, transitioning
485+
the Jira issue — covering a case merge_transition cannot handle.
486+
"""
487+
self.mock_pr.suffix = "closed"
488+
self.mock_pr.status = "Closed"
489+
self.mock_pr.url = "mock_url"
490+
self.mock_pr.downstream = {
491+
"pr_updates": [
492+
{"merge_transition": "Closed"},
493+
{"transition": "Closed"},
494+
],
495+
}
496+
self.mock_existing.fields.status.name = "Open"
497+
498+
d.update_jira_issue(
499+
self.mock_existing, self.mock_pr, self.mock_client, self.mock_config
500+
)
501+
502+
# Only _update_transition fires (merge_transition skipped)
503+
mock_change_status.assert_called_once_with(
504+
self.mock_client, self.mock_existing, "Closed", self.mock_pr
505+
)
506+
400507
@mock.patch(PATH + "update_jira")
401508
@mock.patch(PATH + "d_issue")
402509
def test_sync_with_jira_create_pr_issue_enabled(

0 commit comments

Comments
 (0)