jira_client 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +19 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/jira_client.gemspec +27 -0
- data/lib/jira_client.rb +121 -0
- data/lib/jira_client/api/comments.rb +19 -0
- data/lib/jira_client/api/issues.rb +62 -0
- data/lib/jira_client/api/projects.rb +19 -0
- data/lib/jira_client/api/server.rb +15 -0
- data/lib/jira_client/api/statuses.rb +20 -0
- data/lib/jira_client/api/users.rb +18 -0
- data/lib/jira_client/api/utils.rb +25 -0
- data/lib/jira_client/api/worklogs.rb +26 -0
- data/lib/jira_client/base.rb +54 -0
- data/lib/jira_client/comment.rb +12 -0
- data/lib/jira_client/configuration.rb +27 -0
- data/lib/jira_client/core_ext/string.rb +7 -0
- data/lib/jira_client/error/bad_request.rb +5 -0
- data/lib/jira_client/error/configuration_error.rb +5 -0
- data/lib/jira_client/error/issue_error.rb +5 -0
- data/lib/jira_client/error/resource_not_found.rb +5 -0
- data/lib/jira_client/error/unauthorized.rb +5 -0
- data/lib/jira_client/issue.rb +26 -0
- data/lib/jira_client/project.rb +5 -0
- data/lib/jira_client/server_info.rb +11 -0
- data/lib/jira_client/status.rb +7 -0
- data/lib/jira_client/timetracking.rb +6 -0
- data/lib/jira_client/user.rb +10 -0
- data/lib/jira_client/version.rb +3 -0
- data/lib/jira_client/worklog.rb +10 -0
- data/spec/fixtures/admin.json +17 -0
- data/spec/fixtures/basic_issue.json +6 -0
- data/spec/fixtures/comment.json +23 -0
- data/spec/fixtures/comments.json +30 -0
- data/spec/fixtures/invalid_assignee.json +6 -0
- data/spec/fixtures/invalid_comment.json +6 -0
- data/spec/fixtures/invalid_jql.json +6 -0
- data/spec/fixtures/issue_with_comments.json +33 -0
- data/spec/fixtures/issue_with_description.json +10 -0
- data/spec/fixtures/issue_with_status.json +15 -0
- data/spec/fixtures/issue_with_timetracking.json +16 -0
- data/spec/fixtures/issue_with_worklogs.json +34 -0
- data/spec/fixtures/issues.json +28 -0
- data/spec/fixtures/my_certificate.pem +52 -0
- data/spec/fixtures/no_issues_found.json +6 -0
- data/spec/fixtures/project.json +10 -0
- data/spec/fixtures/projects.json +22 -0
- data/spec/fixtures/server_info.json +14 -0
- data/spec/fixtures/status.json +7 -0
- data/spec/fixtures/statuses.json +16 -0
- data/spec/fixtures/user_doesnt_exist.json +6 -0
- data/spec/fixtures/users.json +22 -0
- data/spec/fixtures/worklog.json +31 -0
- data/spec/jira_client/api/comments_spec.rb +59 -0
- data/spec/jira_client/api/issues_spec.rb +314 -0
- data/spec/jira_client/api/projects_spec.rb +55 -0
- data/spec/jira_client/api/server_spec.rb +31 -0
- data/spec/jira_client/api/statuses_spec.rb +69 -0
- data/spec/jira_client/api/users_spec.rb +56 -0
- data/spec/jira_client/api/worklogs_spec.rb +86 -0
- data/spec/jira_client/configuration_spec.rb +78 -0
- data/spec/jira_client_spec.rb +49 -0
- data/spec/spec_helper.rb +56 -0
- metadata +226 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
{
|
2
|
+
"expand": "schema,names",
|
3
|
+
"startAt": 0,
|
4
|
+
"maxResults": 50,
|
5
|
+
"total": 2,
|
6
|
+
"issues": [
|
7
|
+
{
|
8
|
+
"expand": "editmeta,renderedFields,transitions,changelog,operations",
|
9
|
+
"id": "10100",
|
10
|
+
"self": "http://localhost:2990/jira/rest/api/2/issue/10100",
|
11
|
+
"key": "TEST-2",
|
12
|
+
"fields": {
|
13
|
+
"summary": "Something doesnt work",
|
14
|
+
"description": null
|
15
|
+
}
|
16
|
+
},
|
17
|
+
{
|
18
|
+
"expand": "editmeta,renderedFields,transitions,changelog,operations",
|
19
|
+
"id": "10000",
|
20
|
+
"self": "http://localhost:2990/jira/rest/api/2/issue/10000",
|
21
|
+
"key": "TEST-1",
|
22
|
+
"fields": {
|
23
|
+
"summary": "Testing new feature",
|
24
|
+
"description": null
|
25
|
+
}
|
26
|
+
}
|
27
|
+
]
|
28
|
+
}
|
@@ -0,0 +1,52 @@
|
|
1
|
+
-----BEGIN RSA PRIVATE KEY-----
|
2
|
+
Proc-Type: 4,ENCRYPTED
|
3
|
+
DEK-Info: DES-EDE3-CBC,39EDD4C0F9F5B97D
|
4
|
+
|
5
|
+
ar3c/LrtleaNgO17p+SN3zH30VSCXm4Lg5CNBcnMceWjgVQo3zHnyyxvKZ+zRvT0
|
6
|
+
wZPEpCOG4vZ0j8UUeNrPxZKX2uioNhPYEkhR0N+W57ukzJafQy3TptVmTHkk/t5Y
|
7
|
+
9f88fMgyLoFh+xBuD0iYOv8wp/V9UEFuLTIXExVyGV5Rqv+maKpfYVgIx185qwDE
|
8
|
+
S2gYNEaJBJKu0TOpwO2iLRq2xC2cULJAH5rBlAcVlcX+/MHOa86Yd5WM6/5NJxfG
|
9
|
+
psx0dQj7nZBbjjfzKGUSN230qd3/jwsfuvekHtjvNzERBelqMrpqeLiTI4aCYdpz
|
10
|
+
7vP066/CCLB6k4Zm5rQXID50arDQWfgCMSsBFPZfPHZhshCbHA/IRQg3HWBzSgzP
|
11
|
+
zsIUoTw4carUnaT8KAiooqSY+6iaZFk0gacV6Ax0TRUXc9GtqQ1bRoi58lOkEWjm
|
12
|
+
wyB4xRqSGC7k0wiFGZKSTQSHFkQpy5imSy8XV5yAWxgniFb5zsX0WWvg4FR+wR+h
|
13
|
+
2cYPZuXX4qyFZ8YoeQM5aP0XtrXaSlpWLTrqwIJFQvI/w1MPOj+CI4vZP133UME9
|
14
|
+
Wvog46Yyka4VCFEmvSQvz2OjbSehNrDFIlb2tNhA8VQZ/H3XCm/xmmSm+4ssy1hc
|
15
|
+
ELoJXFickj+ILK9/Ppw7BhvE19N6ZxAAj7zH6PyEdAKtAHdWxOS2qe/+IpEyxTFr
|
16
|
+
XWzhhFRuCixUThVWPwimW1lm5BZ9/IwyeLhbP8jtuwm6lC0DqP/ui4LLzMeinJIY
|
17
|
+
uAzm5tO3ioAlijAUPwgLQuJmZt1hJ994uyAGt0IbdR75QKfFVk3KY07Fci/YV/VX
|
18
|
+
tRlMPtsmVD2uJONpEPwsXZCoOFepU9nuL3woosOHkqbL/EYGbMfP1c8Z696662fS
|
19
|
+
gbTiH5hqTeOsWGylN0+SM+mneRk+czJQd9JwIF6gn225nbV0ymrA9RKE5ISDKrGN
|
20
|
+
7Yi6WefdDxV3GgO2buFiFEXZiLq7lsYHnOqGRH/aM8apkK8Lt9FfecUDewfpnM10
|
21
|
+
pX04U2Kb8iYbY68DPUDlpEmwc1qDS9xyY3n5Z9UiYqRpqdBuIuGnLZenx0LRUX16
|
22
|
+
8t/83vc0AKtMDIb35/PLUltDJzPDIEqF6xF1KE7IRRp9a2Pv+a+4l2wse0aPfes6
|
23
|
+
niI0cEoQAcxyt638T3h6kaWlmXqbM4XhEmFTEXe+24Au9rq2mf41mW1G5KKLupBA
|
24
|
+
OEiHe0OsHF5pUeliVpewyHOYfee9bO8thS9HhiuAahSjMVbOaSSzBxcr4hgHlL7v
|
25
|
+
qwnlfYD0Hd6bhEthLMCnMmFk0A9Y/2Hx7NVhJ1fdvcP/zVmYiJTdSNIFd2izXVn8
|
26
|
+
obu4eFtzj0+cgIER1OM0ln5o2s5GlYFnG11lw7qruSTb9UGZptTaR0zeoIiwBjEn
|
27
|
+
7j3gI3h86DGOT33/J1MKeLZtnkcpD023y4EBtvX8oH4hM8n9oNK6FO87OPeUks6d
|
28
|
+
xCb1riGDc41+gnbKtmxreChuP4CeAG6RpLUdVL6oasy+5gyonWgr1a8OLuCKnHsq
|
29
|
+
fe91FE4hvlAIX7V+mbMf3d0U0N3Rx2Pa74LY2aU+6b6sNqaMMAKlgQ==
|
30
|
+
-----END RSA PRIVATE KEY-----
|
31
|
+
-----BEGIN CERTIFICATE-----
|
32
|
+
MIIDtTCCAp2gAwIBAgIJAPHGRV8yrekRMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
|
33
|
+
BAYTAlVLMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
|
34
|
+
aWRnaXRzIFB0eSBMdGQwHhcNMTMwNTA3MDY0MDEzWhcNMTMwNjA2MDY0MDEzWjBF
|
35
|
+
MQswCQYDVQQGEwJVSzETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
|
36
|
+
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
37
|
+
CgKCAQEAuGHmEDYI0bL3ctMjHPS99QMyE3h8luzcNEDvyLo/cIsYHscs4x10wTwC
|
38
|
+
opzUWLEie0FNFNEPDIhZ1JqalbivTGJmynQ3bQK0RjL0zKeE6cY5z5ie7SmpLED/
|
39
|
+
6ftvPq6HiJCt3X/dCpax+HUYyAIyEJWbxD2IM5ma53rUBXswyfc/bSmGswmIlv0U
|
40
|
+
p5EY10YnQ4n9JUhztl9dP7ag5g3eaZ/1g79OtodUF6mz8TcgTh16Oi7XcNWbYS+T
|
41
|
+
FPOyKKxMFc9HubFhQZ9IZIzIrIDunynre6gPjow+Zdq66NIXVjPtMhYDx50vnYGF
|
42
|
+
4TOhlHGDXfDMaJsl3yKviJZNMz/p2QIDAQABo4GnMIGkMB0GA1UdDgQWBBSQeSrx
|
43
|
+
MLciO7Uv9HLZfqORHEckezB1BgNVHSMEbjBsgBSQeSrxMLciO7Uv9HLZfqORHEck
|
44
|
+
e6FJpEcwRTELMAkGA1UEBhMCVUsxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNV
|
45
|
+
BAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAPHGRV8yrekRMAwGA1UdEwQF
|
46
|
+
MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAf2SjiQXa+0xwdi1Tvr0/UqJevg4/aO
|
47
|
+
lUBWE06DEB8K4QFQpVdRIA/V2kwN+pEJLloMfgmHpjNLIF22USKE3tfWOS1GfFnD
|
48
|
+
ouonv+ULZBFBA3y3pCoRr8+MnJX+8DxxjzauD48EhfCABoaQ5et5QHQEbMXoyjUg
|
49
|
+
1NXwnpT3onmH8M9sFa+uImzXDNxzBd/bD1qjRDLsfAsGixUhttiR+u2WOioiIhEL
|
50
|
+
Nc5QwA7NGBhHVzFyULB5p+C1JoLdzCrE4VJjTnmgaPWM84VdiX8GLzv9SXsQBXwH
|
51
|
+
lfyM/BGfrFznxRaJ4lYOeHbhk46VJqgPEyDHwHOJnI+B1aAs52Ia9tY=
|
52
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,10 @@
|
|
1
|
+
{
|
2
|
+
"self": "http://www.example.com/jira/rest/api/2/project/ABC",
|
3
|
+
"id": "10001",
|
4
|
+
"key": "ABC",
|
5
|
+
"name": "Alphabetical",
|
6
|
+
"avatarUrls": {
|
7
|
+
"16x16": "http://www.example.com/jira/secure/projectavatar?size=small&pid=10001",
|
8
|
+
"48x48": "http://www.example.com/jira/secure/projectavatar?size=large&pid=10001"
|
9
|
+
}
|
10
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
[
|
2
|
+
{
|
3
|
+
"self": "http://www.example.com/jira/rest/api/2/project/EX",
|
4
|
+
"id": "10000",
|
5
|
+
"key": "EX",
|
6
|
+
"name": "Example",
|
7
|
+
"avatarUrls": {
|
8
|
+
"16x16": "http://www.example.com/jira/secure/projectavatar?size=small&pid=10000",
|
9
|
+
"48x48": "http://www.example.com/jira/secure/projectavatar?size=large&pid=10000"
|
10
|
+
}
|
11
|
+
},
|
12
|
+
{
|
13
|
+
"self": "http://www.example.com/jira/rest/api/2/project/ABC",
|
14
|
+
"id": "10001",
|
15
|
+
"key": "ABC",
|
16
|
+
"name": "Alphabetical",
|
17
|
+
"avatarUrls": {
|
18
|
+
"16x16": "http://www.example.com/jira/secure/projectavatar?size=small&pid=10001",
|
19
|
+
"48x48": "http://www.example.com/jira/secure/projectavatar?size=large&pid=10001"
|
20
|
+
}
|
21
|
+
}
|
22
|
+
]
|
@@ -0,0 +1,14 @@
|
|
1
|
+
{
|
2
|
+
"baseUrl": "https://example.jira.com",
|
3
|
+
"version": "5.1.8",
|
4
|
+
"versionNumbers": [
|
5
|
+
5,
|
6
|
+
1,
|
7
|
+
8
|
8
|
+
],
|
9
|
+
"buildNumber": 787,
|
10
|
+
"buildDate": "2012-10-29T00:00:00.000+0000",
|
11
|
+
"serverTime": "2013-04-24T22:01:45.802+0100",
|
12
|
+
"scmInfo": "823790ce17da57e7ed0220e49723c7b00a6d54dc",
|
13
|
+
"serverTitle": "Example JIRA"
|
14
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
[
|
2
|
+
{
|
3
|
+
"self": "http://localhost:8090/jira/rest/api/2.0/status/10000",
|
4
|
+
"description": "The issue is currently being worked on.",
|
5
|
+
"iconUrl": "http://localhost:8090/jira/images/icons/progress.gif",
|
6
|
+
"name": "In Progress",
|
7
|
+
"id": "10000"
|
8
|
+
},
|
9
|
+
{
|
10
|
+
"self": "http://localhost:8090/jira/rest/api/2.0/status/5",
|
11
|
+
"description": "The issue is closed.",
|
12
|
+
"iconUrl": "http://localhost:8090/jira/images/icons/closed.gif",
|
13
|
+
"name": "Closed",
|
14
|
+
"id": "5"
|
15
|
+
}
|
16
|
+
]
|
@@ -0,0 +1,22 @@
|
|
1
|
+
[
|
2
|
+
{
|
3
|
+
"self": "http://www.example.com/jira/rest/api/2/user?username=fred",
|
4
|
+
"name": "fred",
|
5
|
+
"avatarUrls": {
|
6
|
+
"16x16": "http://www.example.com/jira/secure/useravatar?size=small&ownerId=fred",
|
7
|
+
"48x48": "http://www.example.com/jira/secure/useravatar?size=large&ownerId=fred"
|
8
|
+
},
|
9
|
+
"displayName": "Fred F. User",
|
10
|
+
"active": false
|
11
|
+
},
|
12
|
+
{
|
13
|
+
"self": "http://www.example.com/jira/rest/api/2/user?username=andrew",
|
14
|
+
"name": "andrew",
|
15
|
+
"avatarUrls": {
|
16
|
+
"16x16": "http://www.example.com/jira/secure/useravatar?size=small&ownerId=andrew",
|
17
|
+
"48x48": "http://www.example.com/jira/secure/useravatar?size=large&ownerId=andrew"
|
18
|
+
},
|
19
|
+
"displayName": "Andrew Anderson",
|
20
|
+
"active": false
|
21
|
+
}
|
22
|
+
]
|
@@ -0,0 +1,31 @@
|
|
1
|
+
{
|
2
|
+
"startAt": 0,
|
3
|
+
"maxResults": 1,
|
4
|
+
"total": 1,
|
5
|
+
"worklogs": [
|
6
|
+
{
|
7
|
+
"self": "http://www.example.com/jira/rest/api/2.0/issue/10010/worklog/10000",
|
8
|
+
"author": {
|
9
|
+
"self": "http://www.example.com/jira/rest/api/2.0/user?username=fred",
|
10
|
+
"name": "fred",
|
11
|
+
"displayName": "Fred F. User",
|
12
|
+
"active": false
|
13
|
+
},
|
14
|
+
"updateAuthor": {
|
15
|
+
"self": "http://www.example.com/jira/rest/api/2.0/user?username=fred",
|
16
|
+
"name": "fred",
|
17
|
+
"displayName": "Fred F. User",
|
18
|
+
"active": false
|
19
|
+
},
|
20
|
+
"comment": "I did some work here.",
|
21
|
+
"started": "2012-02-15T17:34:37.937-0600",
|
22
|
+
"timeSpent": "3h 20m",
|
23
|
+
"timeSpentSeconds": 12000,
|
24
|
+
"id": "100028",
|
25
|
+
"visibility": {
|
26
|
+
"type": "group",
|
27
|
+
"value": "jira-developers"
|
28
|
+
}
|
29
|
+
}
|
30
|
+
]
|
31
|
+
}
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe JiraClient::API::Comments do
|
4
|
+
|
5
|
+
describe "#find_issue_comments" do
|
6
|
+
|
7
|
+
before do
|
8
|
+
stub_get("/issue/PROJECT-1234/comment").to_return(:body => fixture("comments.json"), :headers => {:content_type => "application/json; charset=utf-8"})
|
9
|
+
@comments = JiraClient.find_issue_comments "PROJECT-1234"
|
10
|
+
end
|
11
|
+
|
12
|
+
it "requests the correct resource" do
|
13
|
+
expect(a_get("/issue/PROJECT-1234/comment")).to have_been_made
|
14
|
+
end
|
15
|
+
it "returns an array of JiraClient::Comment objects" do
|
16
|
+
@comments.should be_a_kind_of Array
|
17
|
+
@comments.each do |comment|
|
18
|
+
comment.should be_a_kind_of JiraClient::Comment
|
19
|
+
end
|
20
|
+
end
|
21
|
+
it "assigns the correct information" do
|
22
|
+
comment = @comments.first
|
23
|
+
comment.body.should == "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque eget venenatis elit. Duis eu justo eget augue iaculis fermentum. Sed semper quam laoreet nisi egestas at posuere augue semper."
|
24
|
+
comment.author.should be_a_kind_of JiraClient::User
|
25
|
+
comment.update_author.should be_a_kind_of JiraClient::User
|
26
|
+
comment.created.should be_a_kind_of DateTime
|
27
|
+
comment.updated.should be_a_kind_of DateTime
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#comment_on_issue" do
|
32
|
+
|
33
|
+
before do
|
34
|
+
stub_post("/issue/PROJECT-1234/comment").with(:body => {"body" => "This is a comment"}).to_return(:status => 201, :body => fixture("comment.json"))
|
35
|
+
@comment = JiraClient.comment_on_issue("PROJECT-1234", "This is a comment")
|
36
|
+
end
|
37
|
+
|
38
|
+
it "requests the correct resource" do
|
39
|
+
expect(a_post("/issue/PROJECT-1234/comment").with(:body => {:body => "This is a comment"})).to have_been_made
|
40
|
+
end
|
41
|
+
it "returns the comment object" do
|
42
|
+
@comment.should be_a_kind_of JiraClient::Comment
|
43
|
+
end
|
44
|
+
it "with the comment text set on the comment object" do
|
45
|
+
@comment.body.should == "This is a comment"
|
46
|
+
end
|
47
|
+
context "without a comment body" do
|
48
|
+
|
49
|
+
before do
|
50
|
+
stub_post("/issue/PROJECT-1234/comment").to_return(:status => 400, :body => fixture("invalid_comment.json"))
|
51
|
+
end
|
52
|
+
|
53
|
+
it "raises a JiraClient::Error::BadRequest" do
|
54
|
+
expect { JiraClient.comment_on_issue("PROJECT-1234", "") }.to raise_error(JiraClient::Error::BadRequest)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,314 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe JiraClient::API::Issues do
|
4
|
+
|
5
|
+
describe "#find_issue_by_key" do
|
6
|
+
context "with no extra data" do
|
7
|
+
|
8
|
+
before do
|
9
|
+
stub_get("/issue/PROJECT-1234").to_return(:body => fixture('basic_issue.json'), :headers => {:content_type => "application/json; charset=utf-8"})
|
10
|
+
end
|
11
|
+
|
12
|
+
it "requests the correct resource" do
|
13
|
+
JiraClient.find_issue_by_key("PROJECT-1234")
|
14
|
+
expect(a_get("/issue/PROJECT-1234")).to have_been_made
|
15
|
+
end
|
16
|
+
it "returns a JiraClient::Issue object" do
|
17
|
+
issue = JiraClient.find_issue_by_key("PROJECT-1234")
|
18
|
+
expect(issue).to be_a_kind_of JiraClient::Issue
|
19
|
+
end
|
20
|
+
it "sets the correct attributes" do
|
21
|
+
issue = JiraClient.find_issue_by_key("PROJECT-1234")
|
22
|
+
expect(issue.key).to eq("PROJECT-1234")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
context "with summary and description" do
|
26
|
+
|
27
|
+
before do
|
28
|
+
stub_get("/issue/PROJECT-1235").with(:query => {:fields => "summary,description"}).to_return(:body => fixture('issue_with_description.json'), :headers => {:content_type => "application/json; charset=utf-8"})
|
29
|
+
@issue = JiraClient.find_issue_by_key("PROJECT-1235", :fields => [:summary, :description])
|
30
|
+
end
|
31
|
+
|
32
|
+
it "requests the correct resource" do
|
33
|
+
expect(a_get("/issue/PROJECT-1235?fields=summary,description")).to have_been_made
|
34
|
+
end
|
35
|
+
it "sets the correct attributes" do
|
36
|
+
expect(@issue.key).to eq("PROJECT-1235")
|
37
|
+
expect(@issue.summary?).to be_true
|
38
|
+
expect(@issue.description?).to be_true
|
39
|
+
expect(@issue.summary).to eq("This is an issue summary")
|
40
|
+
expect(@issue.description).to eq("This is a description")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
context "with a status" do
|
44
|
+
|
45
|
+
before do
|
46
|
+
stub_get("/issue/PROJECT-1236").with(:query => {:fields => "status"}).to_return(:body => fixture("issue_with_status.json"), :headers => {:content_type => "application/json; charset=utf-8"})
|
47
|
+
@issue = JiraClient.find_issue_by_key("PROJECT-1236", :fields => [:status])
|
48
|
+
end
|
49
|
+
|
50
|
+
it "requests the correct resource" do
|
51
|
+
expect(a_get("/issue/PROJECT-1236?fields=status")).to have_been_made
|
52
|
+
end
|
53
|
+
it "sets the correct attributes" do
|
54
|
+
expect(@issue.key).to eq("PROJECT-1236")
|
55
|
+
expect(@issue.status?).to be_true
|
56
|
+
expect(@issue.status).to be_a_kind_of JiraClient::Status
|
57
|
+
end
|
58
|
+
end
|
59
|
+
context "with timetracking" do
|
60
|
+
|
61
|
+
before do
|
62
|
+
stub_get("/issue/PROJECT-1234").with(:query => {:fields => "timetracking"}).to_return(:body => fixture("issue_with_timetracking.json"))
|
63
|
+
@issue = JiraClient.find_issue_by_key("PROJECT-1234", :fields => [:timetracking])
|
64
|
+
end
|
65
|
+
|
66
|
+
it "requests the correct resource" do
|
67
|
+
expect(a_get("/issue/PROJECT-1234?fields=timetracking")).to have_been_made
|
68
|
+
end
|
69
|
+
it "returns a timetracking object" do
|
70
|
+
expect(@issue.timetracking).to be_a_kind_of JiraClient::Timetracking
|
71
|
+
end
|
72
|
+
end
|
73
|
+
context "with worklogs" do
|
74
|
+
|
75
|
+
before do
|
76
|
+
stub_get("/issue/PROJECT-1234").with(:query => {:fields => "worklog"}).to_return(:body => fixture("issue_with_worklogs.json"))
|
77
|
+
@issue = JiraClient.find_issue_by_key("PROJECT-1234", :fields => [:worklog])
|
78
|
+
end
|
79
|
+
|
80
|
+
it "requests the correct resource" do
|
81
|
+
expect(a_get("/issue/PROJECT-1234?fields=worklog")).to have_been_made
|
82
|
+
end
|
83
|
+
it "returns an array of worklog items" do
|
84
|
+
@issue.worklog.should be_a_kind_of Array
|
85
|
+
@issue.worklog.each do |worklog|
|
86
|
+
worklog.should be_a_kind_of JiraClient::Worklog
|
87
|
+
worklog.author.should be_a_kind_of JiraClient::User
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
context "with comments" do
|
92
|
+
|
93
|
+
before do
|
94
|
+
stub_get("/issue/PROJECT-1234").with(:query => {:fields => "comment"}).to_return(:body => fixture("issue_with_comments.json"))
|
95
|
+
@issue = JiraClient.find_issue_by_key("PROJECT-1234", :fields => [:comment])
|
96
|
+
end
|
97
|
+
|
98
|
+
it "requests the correct resource" do
|
99
|
+
expect(a_get("/issue/PROJECT-1234?fields=comment")).to have_been_made
|
100
|
+
end
|
101
|
+
it "returns an array of comment objects" do
|
102
|
+
@issue.comment.should be_a_kind_of Array
|
103
|
+
@issue.comment.each do |comment|
|
104
|
+
comment.should be_a_kind_of JiraClient::Comment
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "#assign_issue" do
|
111
|
+
|
112
|
+
before do
|
113
|
+
stub_put("/issue/PROJECT-1234/assignee").with(:body => {"name" => "testuser"}).to_return(:status => 204)
|
114
|
+
JiraClient.assign_issue("PROJECT-1234", "testuser")
|
115
|
+
end
|
116
|
+
|
117
|
+
it "requests the correct resource" do
|
118
|
+
expect(a_put("/issue/PROJECT-1234/assignee")).to have_been_made
|
119
|
+
end
|
120
|
+
context "with invalid username" do
|
121
|
+
|
122
|
+
before do
|
123
|
+
stub_put("/issue/PROJECT-1234/assignee").with(:body => {"name" => "invalid_user"}).to_return(:status => 400, :body => fixture("invalid_assignee.json"))
|
124
|
+
end
|
125
|
+
|
126
|
+
it "raises a JiraClient::Error::BadRequest error" do
|
127
|
+
expect { JiraClient.assign_issue("PROJECT-1234", "invalid_user") }.to raise_error(JiraClient::Error::BadRequest)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
context "with invalid permissions" do
|
131
|
+
|
132
|
+
before do
|
133
|
+
stub_put("/issue/PROJECT-1234/assignee").with(:body => {"name" => "insufficient_permission_user"}).to_return(:status => 401, :body => fixture("invalid_assignee.json"))
|
134
|
+
end
|
135
|
+
|
136
|
+
it "raises JiraClient::Error::Unauthorized" do
|
137
|
+
expect { JiraClient.assign_issue("PROJECT-1234", "insufficient_permission_user") }.to raise_error(JiraClient::Error::Unauthorized)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
context "with an issue that doesnt exist" do
|
141
|
+
|
142
|
+
before do
|
143
|
+
stub_put("/issue/NOEXIST/assignee").with(:body => {"name" => "admin"}).to_return(:status => 404, :body => fixture("invalid_assignee.json"))
|
144
|
+
end
|
145
|
+
|
146
|
+
it "raises JiraClient::Error::ResourceNotFound" do
|
147
|
+
expect { JiraClient.assign_issue("NOEXIST", "admin") }.to raise_error(JiraClient::Error::ResourceNotFound)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
context "with a user that doesnt exist" do
|
151
|
+
|
152
|
+
before do
|
153
|
+
stub_put("/issue/PROJECT-1234/assignee").with(:body => {"name" => "no_exist_user"}).to_return(:status => 404, :body => fixture("invalid_assignee.json"))
|
154
|
+
end
|
155
|
+
|
156
|
+
it "raises JiraClient::Error::ResourceNotFound" do
|
157
|
+
expect { JiraClient.assign_issue("PROJECT-1234", "no_exist_user") }.to raise_error(JiraClient::Error::ResourceNotFound)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe "#resolve_issue" do
|
163
|
+
|
164
|
+
before do
|
165
|
+
stub_post("/issue/PROJECT-1234/transitions").to_return(:status => 204)
|
166
|
+
end
|
167
|
+
|
168
|
+
it "sends data to the correct resource" do
|
169
|
+
JiraClient.resolve_issue "PROJECT-1234"
|
170
|
+
expect(a_post('/issue/PROJECT-1234/transitions')).to have_been_made
|
171
|
+
end
|
172
|
+
it "sends the correct transition ID" do
|
173
|
+
JiraClient.resolve_issue "PROJECT-1234"
|
174
|
+
expect(a_post('/issue/PROJECT-1234/transitions').with(:body => transition_to(JiraClient::Status::RESOLVE))).to have_been_made
|
175
|
+
end
|
176
|
+
it "sends the resolution if provided" do
|
177
|
+
JiraClient.resolve_issue "PROJECT-1234", :as => "Won't Fix"
|
178
|
+
expect(a_post('/issue/PROJECT-1234/transitions').with(:body => transition_to(JiraClient::Status::RESOLVE, :resolution => "Won't Fix"))).to have_been_made
|
179
|
+
end
|
180
|
+
it "sends a comment if provided" do
|
181
|
+
JiraClient.resolve_issue "PROJECT-1234", :comment => "This is a comment"
|
182
|
+
expect(a_post('/issue/PROJECT-1234/transitions').with(:body => transition_to(JiraClient::Status::RESOLVE, :comment => "This is a comment"))).to have_been_made
|
183
|
+
end
|
184
|
+
it "sends both a comment and a resolution if provided" do
|
185
|
+
JiraClient.resolve_issue "PROJECT-1234", :as => "Can't Reproduce", :comment => "This is a comment"
|
186
|
+
expect(a_post('/issue/PROJECT-1234/transitions').with(:body => transition_to(JiraClient::Status::RESOLVE, :comment => "This is a comment", :resolution => "Can't Reproduce"))).to have_been_made
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
describe "#close_issue" do
|
191
|
+
|
192
|
+
before do
|
193
|
+
stub_post("/issue/PROJECT-1234/transitions").to_return(:status => 204)
|
194
|
+
end
|
195
|
+
|
196
|
+
it "sends data to the correct resource" do
|
197
|
+
JiraClient.close_issue "PROJECT-1234"
|
198
|
+
expect(a_post('/issue/PROJECT-1234/transitions')).to have_been_made
|
199
|
+
end
|
200
|
+
it "sends the correct transition ID" do
|
201
|
+
JiraClient.close_issue "PROJECT-1234"
|
202
|
+
expect(a_post('/issue/PROJECT-1234/transitions').with(:body => transition_to(JiraClient::Status::CLOSE))).to have_been_made
|
203
|
+
end
|
204
|
+
it "sends a comment if provided" do
|
205
|
+
JiraClient.close_issue "PROJECT-1234", :comment => "This is a comment"
|
206
|
+
expect(a_post('/issue/PROJECT-1234/transitions').with(:body => transition_to(JiraClient::Status::CLOSE, :comment => "This is a comment"))).to have_been_made
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
describe "#reopen_issue" do
|
211
|
+
|
212
|
+
before do
|
213
|
+
stub_post("/issue/PROJECT-1234/transitions").to_return(:status => 204)
|
214
|
+
end
|
215
|
+
|
216
|
+
it "sends data to the correct resource" do
|
217
|
+
JiraClient.reopen_issue "PROJECT-1234"
|
218
|
+
expect(a_post('/issue/PROJECT-1234/transitions')).to have_been_made
|
219
|
+
end
|
220
|
+
it "sends the correct transition ID" do
|
221
|
+
JiraClient.reopen_issue "PROJECT-1234"
|
222
|
+
expect(a_post('/issue/PROJECT-1234/transitions').with(:body => transition_to(JiraClient::Status::REOPEN))).to have_been_made
|
223
|
+
end
|
224
|
+
it "sends a comment if provided" do
|
225
|
+
JiraClient.reopen_issue "PROJECT-1234", :comment => "This is a comment"
|
226
|
+
expect(a_post('/issue/PROJECT-1234/transitions').with(:body => transition_to(JiraClient::Status::REOPEN, :comment => "This is a comment"))).to have_been_made
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
describe "#start_progress_on_issue" do
|
231
|
+
|
232
|
+
before do
|
233
|
+
stub_post("/issue/PROJECT-1234/transitions").to_return(:status => 204)
|
234
|
+
end
|
235
|
+
|
236
|
+
it "sends data to the correct resource" do
|
237
|
+
JiraClient.start_progress_on_issue "PROJECT-1234"
|
238
|
+
expect(a_post('/issue/PROJECT-1234/transitions')).to have_been_made
|
239
|
+
end
|
240
|
+
it "sends the correct transition ID (6)" do
|
241
|
+
JiraClient.start_progress_on_issue "PROJECT-1234"
|
242
|
+
expect(a_post('/issue/PROJECT-1234/transitions').with(:body => transition_to(JiraClient::Status::START_PROGRESS))).to have_been_made
|
243
|
+
end
|
244
|
+
it "sends a comment if provided" do
|
245
|
+
JiraClient.start_progress_on_issue "PROJECT-1234", :comment => "This is a comment"
|
246
|
+
expect(a_post('/issue/PROJECT-1234/transitions').with(:body => transition_to(JiraClient::Status::START_PROGRESS, :comment => "This is a comment"))).to have_been_made
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
describe "#find_issues" do
|
251
|
+
|
252
|
+
before do
|
253
|
+
stub_post("/search").with(:body => {:jql => "project = TEST"}).to_return(:status => 200, :body => fixture("issues.json"))
|
254
|
+
@issues = JiraClient.find_issues(:jql => "project = TEST")
|
255
|
+
end
|
256
|
+
|
257
|
+
it "requests the correct resource" do
|
258
|
+
expect(a_post("/search").with(:body => {"jql" => "project = TEST"})).to have_been_made
|
259
|
+
end
|
260
|
+
it "accepts an array of fields to be returned" do
|
261
|
+
stub_post("/search").with(:body => {:fields => ["summary", "description"]}).to_return(:status => 200, :body => fixture("issues.json"))
|
262
|
+
@issues = JiraClient.find_issues(:fields => [:summary, :description])
|
263
|
+
expect(a_post("/search").with(:body => {:fields => ["summary", "description"]})).to have_been_made
|
264
|
+
end
|
265
|
+
it "returns an array of issue objects" do
|
266
|
+
@issues.should be_a_kind_of Array
|
267
|
+
@issues.each do |issue|
|
268
|
+
issue.should be_a_kind_of JiraClient::Issue
|
269
|
+
end
|
270
|
+
end
|
271
|
+
context "when there are no results" do
|
272
|
+
|
273
|
+
before do
|
274
|
+
stub_post("/search").with(:body => {:jql => "project = TEST and status = 'In Progress'"}).to_return(:status => 200, :body => fixture("no_issues_found.json"))
|
275
|
+
end
|
276
|
+
|
277
|
+
it "returns an empty array" do
|
278
|
+
@issues = JiraClient.find_issues(:jql => "project = TEST and status = 'In Progress'")
|
279
|
+
@issues.should be_a_kind_of Array
|
280
|
+
@issues.should be_empty
|
281
|
+
end
|
282
|
+
end
|
283
|
+
context "when there is a problem with the JQL" do
|
284
|
+
|
285
|
+
before do
|
286
|
+
stub_post("/search").with(:body => {:jql => "project = DOESNT_EXIST"}).to_return(:status => 400, :body => fixture("invalid_jql.json"))
|
287
|
+
end
|
288
|
+
|
289
|
+
it "raises a bad request error" do
|
290
|
+
expect { JiraClient.find_issues(:jql => "project = DOESNT_EXIST") }.to raise_error(JiraClient::Error::BadRequest)
|
291
|
+
end
|
292
|
+
it "hints at the problem with the jql" do
|
293
|
+
begin
|
294
|
+
JiraClient.find_issues(:jql => "project = DOESNT_EXIST")
|
295
|
+
rescue JiraClient::Error::BadRequest => e
|
296
|
+
e.message.should include "project"
|
297
|
+
e.message.should include "DOESNT_EXIST"
|
298
|
+
e.message.should include "does not exist"
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
end
|
304
|
+
|
305
|
+
private
|
306
|
+
|
307
|
+
def transition_to(id, opts = {})
|
308
|
+
body = {"transition" => {"id" => id}}
|
309
|
+
body["update"] = {"comment" => [{"add" => {"body" => opts[:comment]}}]} if opts.has_key? :comment
|
310
|
+
body["fields"] = {"resolution" => {"name" => opts[:resolution]}} if opts.has_key? :resolution
|
311
|
+
body
|
312
|
+
end
|
313
|
+
|
314
|
+
end
|