66# See https://aboutcode.org for more information about AboutCode FOSS projects.
77#
88
9+ import base64
910from unittest import mock
1011from urllib .parse import quote
1112
@@ -32,14 +33,14 @@ def test_integrations_is_valid_issue_tracker_id(self):
3233 # GitLab
3334 "https://gitlab.com/group/project" ,
3435 # Jira
35- "https://aboutcode .atlassian.net/browse/PROJ" ,
36- "https://aboutcode .atlassian.net/projects/PROJ" ,
37- "https://aboutcode .atlassian.net/projects/PROJ/" ,
38- "https://aboutcode .atlassian.net/projects/PROJ/summary" ,
39- "https://aboutcode .atlassian.net/jira/software/projects/PROJ" ,
40- "https://aboutcode .atlassian.net/jira/software/projects/PROJ/" ,
41- "https://aboutcode .atlassian.net/jira/software/projects/PROJ/summary" ,
42- "https://aboutcode .atlassian.net/jira/servicedesk/projects/PROJ" ,
36+ "https://example .atlassian.net/browse/PROJ" ,
37+ "https://example .atlassian.net/projects/PROJ" ,
38+ "https://example .atlassian.net/projects/PROJ/" ,
39+ "https://example .atlassian.net/projects/PROJ/summary" ,
40+ "https://example .atlassian.net/jira/software/projects/PROJ" ,
41+ "https://example .atlassian.net/jira/software/projects/PROJ/" ,
42+ "https://example .atlassian.net/jira/software/projects/PROJ/summary" ,
43+ "https://example .atlassian.net/jira/servicedesk/projects/PROJ" ,
4344 ]
4445 for url in valid_urls :
4546 self .assertTrue (is_valid_issue_tracker_id (url ), msg = url )
@@ -58,7 +59,7 @@ def test_integrations_get_class_for_tracker(self):
5859 self .assertIs (get_class_for_tracker ("https://github.com/org/repo" ), GitHubIntegration )
5960 self .assertIs (get_class_for_tracker ("https://gitlab.com/group/project" ), GitLabIntegration )
6061 self .assertIs (
61- get_class_for_tracker ("https://aboutcode .atlassian.net/projects/PROJ" ), JiraIntegration
62+ get_class_for_tracker ("https://example .atlassian.net/projects/PROJ" ), JiraIntegration
6263 )
6364 self .assertIsNone (get_class_for_tracker ("https://example.com" ))
6465
@@ -295,3 +296,122 @@ def test_gitlab_post_comment_calls_post(self, mock_session_post):
295296 json = {"body" : "Test comment" },
296297 timeout = self .gitlab .default_timeout ,
297298 )
299+
300+
301+ class JiraIntegrationTestCase (TestCase ):
302+ def setUp (self ):
303+ patcher = mock .patch ("workflow.models.Request.handle_integrations" , return_value = None )
304+ self .mock_handle_integrations = patcher .start ()
305+ self .addCleanup (patcher .stop )
306+
307+ self .dataspace = Dataspace .objects .create (name = "nexB" )
308+ self .dataspace .set_configuration ("jira_user" , "fake-user" )
309+ self .dataspace .set_configuration ("jira_token" , "fake-token" )
310+ self .super_user = create_superuser ("nexb_user" , self .dataspace )
311+ self .component_ct = ContentType .objects .get (
312+ app_label = "component_catalog" , model = "component"
313+ )
314+ self .request_template = RequestTemplate .objects .create (
315+ name = "Jira Template" ,
316+ description = "Integration test template" ,
317+ content_type = self .component_ct ,
318+ dataspace = self .dataspace ,
319+ issue_tracker_id = "https://example.atlassian.net/browse/PROJ" ,
320+ )
321+ self .question = Question .objects .create (
322+ template = self .request_template ,
323+ label = "Example Question" ,
324+ input_type = "TextField" ,
325+ position = 0 ,
326+ dataspace = self .dataspace ,
327+ )
328+ self .request = self .request_template .create_request (
329+ title = "Example Request" ,
330+ requester = self .super_user ,
331+ serialized_data = '{"Example Question": "Some value"}' ,
332+ )
333+ self .jira = JiraIntegration (dataspace = self .dataspace )
334+
335+ def test_jira_extract_jira_info_valid_urls (self ):
336+ urls = [
337+ "https://example.atlassian.net/browse/PROJ" ,
338+ "https://example.atlassian.net/projects/PROJ" ,
339+ "https://example.atlassian.net/projects/PROJ/" ,
340+ "https://example.atlassian.net/projects/PROJ/summary" ,
341+ "https://example.atlassian.net/jira/software/projects/PROJ" ,
342+ "https://example.atlassian.net/jira/software/projects/PROJ/" ,
343+ "https://example.atlassian.net/jira/software/projects/PROJ/summary" ,
344+ "https://example.atlassian.net/jira/servicedesk/projects/PROJ" ,
345+ ]
346+ for url in urls :
347+ base_url , project_key = JiraIntegration .extract_jira_info (url )
348+ self .assertEqual (base_url , "https://example.atlassian.net" )
349+ self .assertEqual (project_key , "PROJ" )
350+
351+ def test_jira_extract_jira_info_invalid_url (self ):
352+ with self .assertRaises (ValueError ):
353+ JiraIntegration .extract_jira_info ("https://example.com/browse/PROJ" )
354+
355+ def test_jira_get_headers_returns_auth_header (self ):
356+ headers = self .jira .get_headers ()
357+ expected_auth = base64 .b64encode (b"fake-user:fake-token" ).decode ()
358+ self .assertEqual (
359+ headers ,
360+ {
361+ "Authorization" : f"Basic { expected_auth } " ,
362+ "Accept" : "application/json" ,
363+ "Content-Type" : "application/json" ,
364+ },
365+ )
366+
367+ def test_jira_make_issue_title (self ):
368+ title = self .jira .make_issue_title (self .request )
369+ self .assertEqual (title , "[DEJACODE] Example Request" )
370+
371+ def test_jira_make_issue_body_contains_question (self ):
372+ body = self .jira .make_issue_body (self .request )
373+ self .assertIn ("### Example Question" , body )
374+ self .assertIn ("Some value" , body )
375+
376+ @mock .patch ("requests.Session.post" )
377+ def test_jira_create_issue_calls_post (self , mock_session_post ):
378+ mock_session_post .return_value .json .return_value = {"key" : "PROJ-123" }
379+ mock_session_post .return_value .raise_for_status .return_value = None
380+
381+ self .jira .api_url = "https://example.atlassian.net/rest/api/3"
382+ issue = self .jira .create_issue (
383+ project_key = "PROJ" ,
384+ title = "Issue Title" ,
385+ body = "Issue Body" ,
386+ )
387+
388+ self .assertEqual (issue ["key" ], "PROJ-123" )
389+ mock_session_post .assert_called_once ()
390+
391+ @mock .patch ("requests.Session.put" )
392+ def test_jira_update_issue_calls_put (self , mock_session_put ):
393+ mock_session_put .return_value .raise_for_status .return_value = None
394+ self .jira .api_url = "https://example.atlassian.net/rest/api/3"
395+
396+ response = self .jira .update_issue (
397+ issue_id = "PROJ-123" ,
398+ title = "Updated title" ,
399+ body = "Updated body" ,
400+ )
401+
402+ self .assertEqual (response ["id" ], "PROJ-123" )
403+ mock_session_put .assert_called_once ()
404+
405+ @mock .patch ("requests.Session.post" )
406+ def test_jira_post_comment_calls_post (self , mock_session_post ):
407+ mock_session_post .return_value .json .return_value = {"id" : "1001" }
408+ mock_session_post .return_value .raise_for_status .return_value = None
409+
410+ response = self .jira .post_comment (
411+ repo_id = "https://example.atlassian.net" ,
412+ issue_id = "PROJ-123" ,
413+ comment_body = "Test comment" ,
414+ )
415+
416+ self .assertEqual (response ["id" ], "1001" )
417+ mock_session_post .assert_called_once ()
0 commit comments