Skip to content

Commit 631c6d8

Browse files
committed
Add tests
1 parent 269dc9f commit 631c6d8

8 files changed

Lines changed: 8057 additions & 1 deletion

unittests/dojo_test_case.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,12 +488,24 @@ def assert_jira_updated_map_changed(self, test_id, updated_map):
488488
logger.debug("finding!")
489489
self.assertNotEqual(jira_helper.get_jira_updated(finding), updated_map[finding.id])
490490

491+
def assert_jira_status_changed(self, finding_id: int, payload: dict, current_status_name: str, expected_status_name: str, push_to_jira: bool = True): # noqa: FBT001, FBT002
492+
pre_jira_status = self.get_jira_issue_status(finding_id)
493+
self.assertEqual(current_status_name, pre_jira_status.name)
494+
self.patch_finding_api(finding_id, {"push_to_jira": push_to_jira, **payload})
495+
post_jira_status = self.get_jira_issue_status(finding_id)
496+
self.assertEqual(expected_status_name, post_jira_status.name)
497+
491498
# Toggle epic mapping on jira product
492499
def toggle_jira_project_epic_mapping(self, obj, value):
493500
project = jira_helper.get_jira_project(obj)
494501
project.enable_engagement_epic_mapping = value
495502
project.save()
496503

504+
def toggle_jira_finding_sync(self, obj, value):
505+
instance = jira_helper.get_jira_instance(obj)
506+
instance.finding_jira_sync = value
507+
instance.save()
508+
497509
# Return a list of jira issue in json format.
498510
def get_epic_issues(self, engagement):
499511
instance = jira_helper.get_jira_instance(engagement)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"findings": [
3+
{
4+
"title": "High",
5+
"description": "test",
6+
"date": "2025-12-01",
7+
"severity": "High",
8+
"component_name": "Component A"
9+
}
10+
]
11+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"findings": [
3+
{
4+
"title": "Critical",
5+
"description": "test",
6+
"date": "2025-12-01",
7+
"severity": "Critical",
8+
"component_name": "Component A"
9+
},
10+
{
11+
"title": "High",
12+
"description": "test",
13+
"date": "2025-12-01",
14+
"severity": "High",
15+
"component_name": "Component A"
16+
}
17+
]
18+
}

unittests/test_jira_import_and_pushing_api.py

Lines changed: 155 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
import dojo.risk_acceptance.helper as ra_helper
1313
from dojo.jira_link import helper as jira_helper
14-
from dojo.models import Finding, Finding_Group, JIRA_Instance, Risk_Acceptance, User
14+
from dojo.models import Finding, Finding_Group, JIRA_Instance, Risk_Acceptance, Test, User
1515
from unittests.dojo_test_case import (
1616
DojoVCRAPITestCase,
1717
get_unit_tests_path,
@@ -81,6 +81,9 @@ def setUp(self):
8181
self.zap_sample5_filename = get_unit_tests_scans_path("zap") / "5_zap_sample_one.xml"
8282
self.npm_groups_sample_filename = get_unit_tests_scans_path("npm_audit") / "many_vuln_with_groups.json"
8383
self.npm_groups_sample_filename2 = get_unit_tests_scans_path("npm_audit") / "many_vuln_with_groups_different_titles.json"
84+
self.generic_one_finding_with_component_name = get_unit_tests_scans_path("generic") / "generic_one_finding_with_component_name.json"
85+
self.generic_two_findings_same_component_name = get_unit_tests_scans_path("generic") / "generic_two_findings_same_component_name.json"
86+
self.generic_report_with_findings = get_unit_tests_scans_path("generic") / "generic_report1.json"
8487
self.clair_few_findings = get_unit_tests_scans_path("clair") / "clair_few_vuln.json"
8588
self.client.force_login(self.get_test_admin())
8689

@@ -1070,6 +1073,157 @@ def test_bulk_edit_mixed_findings_and_groups_jira_push_bug(self, mock_webhooks,
10701073
self.assertEqual(len(group_calls), 2, "Expected 2 finding groups to be pushed")
10711074
self.assertEqual(len(individual_calls), 2, "Expected 2 individual findings to be pushed")
10721075

1076+
def test_keep_sync_push_finding_then_update_individual_finding_with_no_push(self):
1077+
"""
1078+
With keep_sync enabled, import a scan with push_to_jira=True, then update one of the
1079+
findings with push_to_jira=False, but keep_sync enabled, should update the issue in JIRA
1080+
"""
1081+
# Set the finding sync setting
1082+
import0 = self.import_scan_with_params(
1083+
self.generic_one_finding_with_component_name,
1084+
scan_type="Generic Findings Import",
1085+
push_to_jira=True,
1086+
verified=True,
1087+
)
1088+
test_id = import0["test"]
1089+
test = Test.objects.get(id=test_id)
1090+
self.assert_jira_issue_count_in_test(test_id, 1)
1091+
self.assert_jira_group_issue_count_in_test(test_id, 0)
1092+
# Enable the finding sync
1093+
self.toggle_jira_finding_sync(test, value=True)
1094+
# Get one of the findings
1095+
finding_id = self.get_test_findings_api(test_id)["results"][0]["id"]
1096+
# Ensure the status is what we expect before the update
1097+
pre_jira_status = self.get_jira_issue_status(finding_id)
1098+
self.assertEqual("Backlog", pre_jira_status.name)
1099+
# Make the update to the finding
1100+
self.patch_finding_api(finding_id, {"push_to_jira": False, "is_mitigated": True})
1101+
# Verify that the status did in fact change
1102+
post_jira_status = self.get_jira_issue_status(finding_id)
1103+
self.assertEqual("Done", post_jira_status.name)
1104+
# by asserting full cassette is played we know issues have been updated in JIRA
1105+
self.assert_cassette_played()
1106+
1107+
def test_keep_sync_push_finding_then_reimport_with_no_push(self):
1108+
"""
1109+
With keep_sync enabled, import a scan with push_to_jira=True, then reimport a second
1110+
scan with push_to_jira=False that closes one of the findings, should update the issue in JIRA
1111+
"""
1112+
# Set the finding sync setting
1113+
import0 = self.import_scan_with_params(
1114+
self.generic_two_findings_same_component_name,
1115+
scan_type="Generic Findings Import",
1116+
push_to_jira=True,
1117+
verified=True,
1118+
)
1119+
test_id = import0["test"]
1120+
test = Test.objects.get(id=test_id)
1121+
self.assert_jira_issue_count_in_test(test_id, 2)
1122+
self.assert_jira_group_issue_count_in_test(test_id, 0)
1123+
# Enable the finding sync
1124+
self.toggle_jira_finding_sync(test, value=True)
1125+
# Get the finding that will be closing in the next reimport
1126+
finding_id = self.get_test_findings_api(test_id, severity="Critical")["results"][0]["id"]
1127+
# Ensure the status is what we expect before the update
1128+
pre_jira_status = self.get_jira_issue_status(finding_id)
1129+
self.assertEqual("Backlog", pre_jira_status.name)
1130+
# Reimport with a different file that has one finding closed, but push_to_jira=False
1131+
import0 = self.reimport_scan_with_params(
1132+
test_id,
1133+
self.generic_one_finding_with_component_name,
1134+
scan_type="Generic Findings Import",
1135+
push_to_jira=False,
1136+
verified=True,
1137+
close_old_findings=True,
1138+
)
1139+
# Verify that the status did in fact change
1140+
post_jira_status = self.get_jira_issue_status(finding_id)
1141+
self.assertEqual("Done", post_jira_status.name)
1142+
# by asserting full cassette is played we know issues have been updated in JIRA
1143+
self.assert_cassette_played()
1144+
1145+
def test_keep_sync_push_finding_groups_then_reimport_empty_file_with_no_push_change_status(self):
1146+
"""
1147+
With keep_sync enabled, import a scan with push_to_jira=True that creates a group, then reimport
1148+
an empty scan with push_to_jira=False that closes the finding in the group, should update the
1149+
issue in JIRA to closed
1150+
"""
1151+
# Set the finding sync setting
1152+
import0 = self.import_scan_with_params(
1153+
self.generic_two_findings_same_component_name,
1154+
scan_type="Generic Findings Import",
1155+
push_to_jira=True,
1156+
verified=True,
1157+
group_by="component_name",
1158+
)
1159+
test_id = import0["test"]
1160+
test = Test.objects.get(id=test_id)
1161+
self.assert_jira_issue_count_in_test(test_id, 0)
1162+
self.assert_jira_group_issue_count_in_test(test_id, 1)
1163+
# Enable the finding sync
1164+
self.toggle_jira_finding_sync(test, value=True)
1165+
# Get the finding that will be closing in the next reimport
1166+
finding_id = self.get_test_findings_api(test_id, severity="Critical")["results"][0]["id"]
1167+
# Ensure the status is what we expect before the update
1168+
pre_jira_status = self.get_jira_issue_status(finding_id)
1169+
self.assertEqual("Backlog", pre_jira_status.name)
1170+
# Reimport with a different file that has one finding closed, but push_to_jira=False
1171+
import0 = self.reimport_scan_with_params(
1172+
test_id,
1173+
self.generic_report_with_findings,
1174+
scan_type="Generic Findings Import",
1175+
push_to_jira=False,
1176+
verified=True,
1177+
close_old_findings=True,
1178+
group_by="component_name",
1179+
)
1180+
# Verify that the status did in fact change
1181+
post_jira_status = self.get_jira_issue_status(finding_id)
1182+
self.assertEqual("Done", post_jira_status.name)
1183+
# by asserting full cassette is played we know issues have been updated in JIRA
1184+
self.assert_cassette_played()
1185+
1186+
def test_keep_sync_push_finding_groups_then_reimport_empty_file_with_no_push_change_priority(self):
1187+
"""
1188+
With keep_sync enabled, import a scan with push_to_jira=True that creates a group, then reimport
1189+
an empty scan with push_to_jira=False that closes the finding in the group, this should leave the
1190+
the high severity finding in the group, and reduce the priority from Critical to High
1191+
"""
1192+
# Set the finding sync setting
1193+
import0 = self.import_scan_with_params(
1194+
self.generic_two_findings_same_component_name,
1195+
scan_type="Generic Findings Import",
1196+
push_to_jira=True,
1197+
verified=True,
1198+
group_by="component_name",
1199+
)
1200+
test_id = import0["test"]
1201+
test = Test.objects.get(id=test_id)
1202+
self.assert_jira_issue_count_in_test(test_id, 0)
1203+
self.assert_jira_group_issue_count_in_test(test_id, 1)
1204+
# Enable the finding sync
1205+
self.toggle_jira_finding_sync(test, value=True)
1206+
# Get the finding that will stay open in the next reimport
1207+
finding_id = self.get_test_findings_api(test_id, severity="High")["results"][0]["id"]
1208+
# Get the priority that we are starting out with
1209+
pre_jira_priority = self.get_jira_issue_priority(finding_id)
1210+
self.assertEqual("Highest", pre_jira_priority.name)
1211+
# Reimport with a different file that has one finding closed, but push_to_jira=False
1212+
import0 = self.reimport_scan_with_params(
1213+
test_id,
1214+
self.generic_one_finding_with_component_name,
1215+
scan_type="Generic Findings Import",
1216+
push_to_jira=False,
1217+
verified=True,
1218+
close_old_findings=True,
1219+
group_by="component_name",
1220+
)
1221+
# Verify that the priority did in fact change
1222+
post_jira_priority = self.get_jira_issue_priority(finding_id)
1223+
self.assertEqual("High", post_jira_priority.name)
1224+
# by asserting full cassette is played we know issues have been updated in JIRA
1225+
self.assert_cassette_played()
1226+
10731227
# creation of epic via the UI is already tested in test_jira_config_engagement_epic, so
10741228
# we take a shortcut here as creating an engagement with epic mapping via the API is not implemented yet
10751229
def create_engagement_epic(self, engagement):

0 commit comments

Comments
 (0)