Skip to content

Commit

Permalink
Jira Cloud user support (#1109)
Browse files Browse the repository at this point in the history
* test_user allow_on_cloud, with appropriate fixes to jira.resources

* update test_generic_resource

* update search_allowed_users_for_issue() for Jira Cloud

* add a search function to the Jira Cloud tests

* add test_search_users() to allow_on_cloud
  • Loading branch information
adehad authored Oct 24, 2021
1 parent 11b87e2 commit e68bf79
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 60 deletions.
8 changes: 6 additions & 2 deletions jira/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2897,7 +2897,11 @@ def user(self, id: str, expand: Optional[Any] = None) -> User:
Returns:
User
"""
user = User(self._options, self._session)
user = User(
self._options,
self._session,
_query_param="accountId" if self._is_cloud else "username",
)
params = {}
if expand is not None:
params["expand"] = expand
Expand Down Expand Up @@ -3152,7 +3156,7 @@ def search_allowed_users_for_issue(
Returns:
ResultList
"""
params = {"username": user}
params = {"query" if self._is_cloud else "username": user}
if issueKey is not None:
params["issueKey"] = issueKey
if projectKey is not None:
Expand Down
10 changes: 8 additions & 2 deletions jira/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -1088,8 +1088,14 @@ def __init__(
options: Dict[str, str],
session: ResilientSession,
raw: Dict[str, Any] = None,
*,
_query_param: str = "username",
):
Resource.__init__(self, "user?username={0}", options, session)
# Handle self-hosted Jira and Jira Cloud differently
if raw and "accountId" in raw["self"]:
_query_param = "accountId"

Resource.__init__(self, f"user?{_query_param}" + "={0}", options, session)
if raw:
self._parse_raw(raw)
self.raw: Dict[str, Any] = cast(Dict[str, Any], self.raw)
Expand Down Expand Up @@ -1409,7 +1415,7 @@ def dict2resource(
r"securitylevel/[^/]+$": SecurityLevel,
r"status/[^/]+$": Status,
r"statuscategory/[^/]+$": StatusCategory,
r"user\?(username|key).+$": User,
r"user\?(username|key|accountId).+$": User,
r"group\?groupname.+$": Group,
r"version/[^/]+$": Version,
# GreenHopper specific resources
Expand Down
5 changes: 5 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ def setUp(self) -> None:
self.project_b = self.test_manager.project_b
self.project_a = self.test_manager.project_a

@property
def identifying_user_property(self) -> str:
"""Literal["accountId", "name"]: Depending on if Jira Cloud or Server"""
return "accountId" if self.is_jira_cloud_ci else "name"

@property
def is_jira_cloud_ci(self) -> bool:
"""is running on Jira Cloud"""
Expand Down
83 changes: 33 additions & 50 deletions tests/resources/test_generic_resource.py
Original file line number Diff line number Diff line change
@@ -1,55 +1,38 @@
import unittest
import pytest

from flaky import flaky
import jira.resources

from jira.resources import (
Group,
Issue,
Project,
Role,
UnknownResource,
cls_for_resource,
)
MOCK_URL = "http://customized-jira.com/rest/"


@flaky
class ResourceTests(unittest.TestCase):
def setUp(self):
pass
def url_test_case(example_url: str):
return f"{MOCK_URL}{example_url}"

def test_cls_for_resource(self):
self.assertEqual(
cls_for_resource(
"https://jira.atlassian.com/rest/\
api/latest/issue/JRA-1330"
),
Issue,
)
self.assertEqual(
cls_for_resource(
"http://localhost:2990/jira/rest/\
api/latest/project/BULK"
),
Project,
)
self.assertEqual(
cls_for_resource(
"http://imaginary-jira.com/rest/\
api/latest/project/IMG/role/10002"
),
Role,
)
self.assertEqual(
cls_for_resource(
"http://customized-jira.com/rest/\
plugin-resource/4.5/json/getMyObject"
),
UnknownResource,
)
self.assertEqual(
cls_for_resource(
"http://customized-jira.com/rest/\
group?groupname=bla"
),
Group,
)

class TestResource:
@pytest.mark.parametrize(
["example_url", "expected_class"],
# fmt: off
[
(url_test_case("api/latest/issue/JRA-1330"), jira.resources.Issue),
(url_test_case("api/latest/project/BULK"), jira.resources.Project),
(url_test_case("api/latest/project/IMG/role/10002"), jira.resources.Role),
(url_test_case("plugin-resource/4.5/json/getMyObject"), jira.resources.UnknownResource),
(url_test_case("group?groupname=bla"), jira.resources.Group),
(url_test_case("user?username=bla"), jira.resources.User), # Jira Server / Data Center
(url_test_case("user?accountId=bla"), jira.resources.User), # Jira Cloud
],
# fmt: on
ids=[
"issue",
"project",
"role",
"unknown_resource",
"group",
"user",
"user_cloud",
],
)
def test_cls_for_resource(self, example_url, expected_class):
"""Test the regex recognizes the right class for a given URL."""
assert jira.resources.cls_for_resource(example_url) == expected_class
32 changes: 26 additions & 6 deletions tests/resources/test_user.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import os

from tests.conftest import TEST_ICON_PATH, JiraTestCase
from jira.resources import User
from tests.conftest import TEST_ICON_PATH, JiraTestCase, allow_on_cloud


class UserTests(JiraTestCase):
def setUp(self):
JiraTestCase.setUp(self)
self.issue = self.test_manager.project_b_issue3

@allow_on_cloud
def test_user(self):
user = self.jira.user(self.test_manager.user_admin.name)
self.assertTrue(user.name)
"""Test that a user can be returned and is the right class"""
# GIVEN: a User
expected_user = self.test_manager.user_admin
# WHEN: The user is searched for using its identifying attribute
user = self.jira.user(getattr(expected_user, self.identifying_user_property))
# THEN: it is of the right type, and has an email address of the right format
assert isinstance(user, User)
self.assertRegex(
user.emailAddress, r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$"
)
Expand Down Expand Up @@ -148,11 +155,22 @@ def test_delete_user_avatar(self):
)
self.jira.delete_user_avatar(self.test_manager.CI_JIRA_ADMIN, props["id"])

@allow_on_cloud
def test_search_users(self):
users = self.jira.search_users(self.test_manager.CI_JIRA_ADMIN)
# WHEN: the search_users function is called with a requested user
if self.is_jira_cloud_ci:
users = self.jira.search_users(query=self.test_manager.CI_JIRA_ADMIN)
else:
users = self.jira.search_users(self.test_manager.CI_JIRA_ADMIN)
# THEN: We get a list of User objects
self.assertGreaterEqual(len(users), 1)
usernames = map(lambda user: user.name, users)
self.assertIn(self.test_manager.user_admin.name, usernames)
self.assertIsInstance(users[0], User)
# and the requested user can be found in this list
user_ids = [getattr(user, self.identifying_user_property) for user in users]
self.assertIn(
getattr(self.test_manager.user_admin, self.identifying_user_property),
user_ids,
)

def test_search_users_maxresults(self):
users = self.jira.search_users(self.test_manager.CI_JIRA_USER, maxResults=1)
Expand All @@ -164,9 +182,11 @@ def test_search_allowed_users_for_issue_by_project(self):
)
self.assertGreaterEqual(len(users), 1)

@allow_on_cloud
def test_search_allowed_users_for_issue_by_issue(self):
users = self.jira.search_allowed_users_for_issue("a", issueKey=self.issue)
self.assertGreaterEqual(len(users), 1)
self.assertIsInstance(users[0], User)

def test_search_allowed_users_for_issue_maxresults(self):
users = self.jira.search_allowed_users_for_issue(
Expand Down

0 comments on commit e68bf79

Please sign in to comment.