mirror of
https://github.com/hanzoai/sentinel.git
synced 2026-09-29 22:34:33 +00:00
299 lines
13 KiB
Python
299 lines
13 KiB
Python
from __future__ import annotations
|
|
|
|
from functools import cached_property
|
|
from typing import Any
|
|
|
|
import responses
|
|
from django.contrib.auth.models import AnonymousUser
|
|
from django.test import RequestFactory
|
|
from django.urls import reverse
|
|
|
|
from sentry.testutils.cases import TestCase
|
|
from sentry.utils import json
|
|
from sentry_plugins.jira.plugin import JiraPlugin
|
|
|
|
create_meta_response = {
|
|
"expand": "projects",
|
|
"projects": [
|
|
{
|
|
"expand": "issuetypes",
|
|
"self": "https://getsentry.atlassian.net/rest/api/2/project/10000",
|
|
"id": "10000",
|
|
"key": "SEN",
|
|
"name": "Sentry",
|
|
"avatarUrls": {
|
|
"48x48": "https://getsentry.atlassian.net/secure/projectavatar?avatarId=10324",
|
|
"24x24": "https://getsentry.atlassian.net/secure/projectavatar?size=small&avatarId=10324",
|
|
"16x16": "https://getsentry.atlassian.net/secure/projectavatar?size=xsmall&avatarId=10324",
|
|
"32x32": "https://getsentry.atlassian.net/secure/projectavatar?size=medium&avatarId=10324",
|
|
},
|
|
"issuetypes": [
|
|
{
|
|
"self": "https://getsentry.atlassian.net/rest/api/2/issuetype/10002",
|
|
"id": "10002",
|
|
"description": "A task that needs to be done.",
|
|
"iconUrl": "https://getsentry.atlassian.net/secure/viewavatar?size=xsmall&avatarId=10318&avatarType=issuetype",
|
|
"name": "Task",
|
|
"subtask": False,
|
|
"expand": "fields",
|
|
"fields": {
|
|
"summary": {
|
|
"required": True,
|
|
"schema": {"type": "string", "system": "summary"},
|
|
"name": "Summary",
|
|
"hasDefaultValue": False,
|
|
"operations": ["set"],
|
|
},
|
|
"issuetype": {
|
|
"required": True,
|
|
"schema": {"type": "issuetype", "system": "issuetype"},
|
|
"name": "Issue Type",
|
|
"hasDefaultValue": False,
|
|
"operations": [],
|
|
"allowedValues": [
|
|
{
|
|
"self": "https://getsentry.atlassian.net/rest/api/2/issuetype/10002",
|
|
"id": "10002",
|
|
"description": "A task that needs to be done.",
|
|
"iconUrl": "https://getsentry.atlassian.net/secure/viewavatar?size=xsmall&avatarId=10318&avatarType=issuetype",
|
|
"name": "Task",
|
|
"subtask": False,
|
|
"avatarId": 10318,
|
|
}
|
|
],
|
|
},
|
|
"components": {
|
|
"required": False,
|
|
"schema": {
|
|
"type": "array",
|
|
"items": "component",
|
|
"system": "components",
|
|
},
|
|
"name": "Component/s",
|
|
"hasDefaultValue": False,
|
|
"operations": ["add", "set", "remove"],
|
|
"allowedValues": [],
|
|
},
|
|
"description": {
|
|
"required": False,
|
|
"schema": {"type": "string", "system": "description"},
|
|
"name": "Description",
|
|
"hasDefaultValue": False,
|
|
"operations": ["set"],
|
|
},
|
|
"project": {
|
|
"required": True,
|
|
"schema": {"type": "project", "system": "project"},
|
|
"name": "Project",
|
|
"hasDefaultValue": False,
|
|
"operations": ["set"],
|
|
"allowedValues": [
|
|
{
|
|
"self": "https://getsentry.atlassian.net/rest/api/2/project/10000",
|
|
"id": "10000",
|
|
"key": "SEN",
|
|
"name": "Sentry",
|
|
"avatarUrls": {
|
|
"48x48": "https://getsentry.atlassian.net/secure/projectavatar?avatarId=10324",
|
|
"24x24": "https://getsentry.atlassian.net/secure/projectavatar?size=small&avatarId=10324",
|
|
"16x16": "https://getsentry.atlassian.net/secure/projectavatar?size=xsmall&avatarId=10324",
|
|
"32x32": "https://getsentry.atlassian.net/secure/projectavatar?size=medium&avatarId=10324",
|
|
},
|
|
}
|
|
],
|
|
},
|
|
"reporter": {
|
|
"required": True,
|
|
"schema": {"type": "user", "system": "reporter"},
|
|
"name": "Reporter",
|
|
"autoCompleteUrl": "https://getsentry.atlassian.net/rest/api/latest/user/search?username=",
|
|
"hasDefaultValue": False,
|
|
"operations": ["set"],
|
|
},
|
|
"fixVersions": {
|
|
"required": False,
|
|
"schema": {
|
|
"type": "array",
|
|
"items": "version",
|
|
"system": "fixVersions",
|
|
},
|
|
"name": "Fix Version/s",
|
|
"hasDefaultValue": False,
|
|
"operations": ["set", "add", "remove"],
|
|
"allowedValues": [],
|
|
},
|
|
"priority": {
|
|
"required": False,
|
|
"schema": {"type": "priority", "system": "priority"},
|
|
"name": "Priority",
|
|
"hasDefaultValue": True,
|
|
"operations": ["set"],
|
|
"allowedValues": [
|
|
{
|
|
"self": "https://getsentry.atlassian.net/rest/api/2/priority/1",
|
|
"iconUrl": "https://getsentry.atlassian.net/images/icons/priorities/highest.svg",
|
|
"name": "Highest",
|
|
"id": "1",
|
|
}
|
|
],
|
|
},
|
|
"customfield_10003": {
|
|
"required": False,
|
|
"schema": {
|
|
"type": "array",
|
|
"items": "string",
|
|
"custom": "com.pyxis.greenhopper.jira:gh-sprint",
|
|
"customId": 10003,
|
|
},
|
|
"name": "Sprint",
|
|
"hasDefaultValue": False,
|
|
"operations": ["set"],
|
|
},
|
|
"labels": {
|
|
"required": False,
|
|
"schema": {"type": "array", "items": "string", "system": "labels"},
|
|
"name": "Labels",
|
|
"autoCompleteUrl": "https://getsentry.atlassian.net/rest/api/1.0/labels/suggest?query=",
|
|
"hasDefaultValue": False,
|
|
"operations": ["add", "set", "remove"],
|
|
},
|
|
"attachment": {
|
|
"required": False,
|
|
"schema": {
|
|
"type": "array",
|
|
"items": "attachment",
|
|
"system": "attachment",
|
|
},
|
|
"name": "Attachment",
|
|
"hasDefaultValue": False,
|
|
"operations": [],
|
|
},
|
|
"assignee": {
|
|
"required": False,
|
|
"schema": {"type": "user", "system": "assignee"},
|
|
"name": "Assignee",
|
|
"autoCompleteUrl": "https://getsentry.atlassian.net/rest/api/latest/user/assignable/search?issueKey=null&username=",
|
|
"hasDefaultValue": False,
|
|
"operations": ["set"],
|
|
},
|
|
},
|
|
}
|
|
],
|
|
}
|
|
],
|
|
}
|
|
|
|
issue_response: dict[str, Any] = {
|
|
"key": "SEN-19",
|
|
"id": "10708",
|
|
"fields": {"summary": "TypeError: 'set' object has no attribute '__getitem__'"},
|
|
}
|
|
|
|
|
|
class JiraPluginTest(TestCase):
|
|
@cached_property
|
|
def plugin(self):
|
|
return JiraPlugin()
|
|
|
|
@cached_property
|
|
def request(self):
|
|
return RequestFactory()
|
|
|
|
def test_conf_key(self):
|
|
assert self.plugin.conf_key == "jira"
|
|
|
|
def test_get_issue_label(self):
|
|
group = self.create_group(message="Hello world", culprit="foo.bar")
|
|
assert self.plugin.get_issue_label(group, "SEN-1") == "SEN-1"
|
|
|
|
def test_get_issue_url(self):
|
|
self.plugin.set_option("instance_url", "https://getsentry.atlassian.net", self.project)
|
|
group = self.create_group(message="Hello world", culprit="foo.bar")
|
|
assert (
|
|
self.plugin.get_issue_url(group, "SEN-1")
|
|
== "https://getsentry.atlassian.net/browse/SEN-1"
|
|
)
|
|
|
|
def test_is_configured(self):
|
|
assert self.plugin.is_configured(None, self.project) is False
|
|
self.plugin.set_option("default_project", "SEN", self.project)
|
|
assert self.plugin.is_configured(None, self.project) is True
|
|
|
|
@responses.activate
|
|
def test_create_issue(self):
|
|
responses.add(
|
|
responses.GET,
|
|
"https://getsentry.atlassian.net/rest/api/2/issue/createmeta",
|
|
json=create_meta_response,
|
|
)
|
|
responses.add(
|
|
responses.POST,
|
|
"https://getsentry.atlassian.net/rest/api/2/issue",
|
|
json={"key": "SEN-1"},
|
|
)
|
|
self.plugin.set_option("instance_url", "https://getsentry.atlassian.net", self.project)
|
|
group = self.create_group(message="Hello world", culprit="foo.bar")
|
|
|
|
request = self.request.get("/")
|
|
request.user = AnonymousUser()
|
|
form_data = {
|
|
"title": "Hello",
|
|
"description": "Fix this.",
|
|
"issuetype": "bug",
|
|
"project": "SEN",
|
|
}
|
|
assert self.plugin.create_issue(request, group, form_data) == "SEN-1"
|
|
|
|
@responses.activate
|
|
def test_link_issue(self):
|
|
responses.add(
|
|
responses.GET,
|
|
"https://getsentry.atlassian.net/rest/api/2/issue/SEN-19",
|
|
json=issue_response,
|
|
)
|
|
self.plugin.set_option("instance_url", "https://getsentry.atlassian.net", self.project)
|
|
group = self.create_group(message="Hello world", culprit="foo.bar")
|
|
|
|
request = self.request.get("/")
|
|
request.user = AnonymousUser()
|
|
form_data = {"issue_id": "SEN-19"}
|
|
assert (
|
|
self.plugin.link_issue(request, group, form_data)["title"]
|
|
== issue_response["fields"]["summary"]
|
|
)
|
|
|
|
def test_no_secrets(self):
|
|
self.user = self.create_user("[email protected]")
|
|
self.org = self.create_organization(owner=self.user, name="Rowdy Tiger")
|
|
self.team = self.create_team(organization=self.org, name="Mariachi Band")
|
|
self.project = self.create_project(organization=self.org, teams=[self.team], name="Bengal")
|
|
self.login_as(self.user)
|
|
self.plugin.set_option("password", "abcdef", self.project)
|
|
url = reverse(
|
|
"sentry-api-0-project-plugin-details", args=[self.org.slug, self.project.slug, "jira"]
|
|
)
|
|
res = self.client.get(url)
|
|
config = json.loads(res.content)["config"]
|
|
password_config = [item for item in config if item["name"] == "password"][0]
|
|
assert password_config.get("type") == "secret"
|
|
assert password_config.get("value") is None
|
|
assert password_config.get("hasSavedValue") is True
|
|
assert password_config.get("prefix") == ""
|
|
|
|
def test_get_formatted_user(self):
|
|
assert self.plugin._get_formatted_user(
|
|
{"displayName": "Foo Bar", "emailAddress": "[email protected]", "name": "foobar"}
|
|
) == {"text": "Foo Bar - [email protected] (foobar)", "id": "foobar"}
|
|
|
|
# test weird addon users that don't have email addresses
|
|
assert self.plugin._get_formatted_user(
|
|
{
|
|
"name": "robot",
|
|
"avatarUrls": {
|
|
"16x16": "https://avatar-cdn.atlassian.com/someid",
|
|
"24x24": "https://avatar-cdn.atlassian.com/someotherid",
|
|
},
|
|
"self": "https://something.atlassian.net/rest/api/2/user?username=someaddon",
|
|
}
|
|
) == {"id": "robot", "text": "robot (robot)"}
|