jiralicious 0.0.6
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/.document +5 -0
- data/.gitignore +10 -0
- data/.rspec +1 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/README.rdoc +21 -0
- data/Rakefile +16 -0
- data/jiralicious.gemspec +27 -0
- data/lib/jiralicious.rb +27 -0
- data/lib/jiralicious/configuration.rb +35 -0
- data/lib/jiralicious/errors.rb +17 -0
- data/lib/jiralicious/issue.rb +56 -0
- data/lib/jiralicious/parsers/field_parser.rb +43 -0
- data/lib/jiralicious/search.rb +26 -0
- data/lib/jiralicious/search_result.rb +17 -0
- data/lib/jiralicious/session.rb +100 -0
- data/lib/jiralicious/version.rb +3 -0
- data/spec/configuration_spec.rb +29 -0
- data/spec/field_parser_spec.rb +72 -0
- data/spec/fixtures/issue.json +167 -0
- data/spec/fixtures/search.json +11 -0
- data/spec/fixtures/transitions.json +65 -0
- data/spec/issue_spec.rb +96 -0
- data/spec/jiralicious_spec.rb +16 -0
- data/spec/search_result_spec.rb +42 -0
- data/spec/search_spec.rb +43 -0
- data/spec/session_spec.rb +278 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/support/configuration.rb +10 -0
- data/spec/support/http.rb +34 -0
- metadata +144 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
3
|
+
|
4
|
+
describe Jiralicious::Configuration do
|
5
|
+
before :each do
|
6
|
+
Jiralicious.reset
|
7
|
+
end
|
8
|
+
|
9
|
+
it "sets the options to their default value" do
|
10
|
+
Jiralicious.username.should be_nil
|
11
|
+
Jiralicious.password.should be_nil
|
12
|
+
Jiralicious.uri.should be_nil
|
13
|
+
Jiralicious.api_version.should == "latest"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "allows setting of options in a block" do
|
17
|
+
Jiralicious.configure do |config|
|
18
|
+
config.username = "jstewart"
|
19
|
+
config.password = "derp"
|
20
|
+
config.uri = "http://example.com/foo/bar"
|
21
|
+
config.api_version = "2.0aplha"
|
22
|
+
end
|
23
|
+
|
24
|
+
Jiralicious.username.should == "jstewart"
|
25
|
+
Jiralicious.password.should == "derp"
|
26
|
+
Jiralicious.uri = "http://example.com/foo/bar"
|
27
|
+
Jiralicious.api_version = "2.0aplha"
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
3
|
+
|
4
|
+
class ParserMock
|
5
|
+
include Jiralicious::Parsers::FieldParser
|
6
|
+
|
7
|
+
def initialize(parsed)
|
8
|
+
parse!(parsed)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe Jiralicious::Parsers::FieldParser do
|
13
|
+
context "parse!" do
|
14
|
+
before :each do
|
15
|
+
@parsed_data = {
|
16
|
+
"testfield" => {"name" => "testfield", "value" => "Test Data"},
|
17
|
+
"methods" => {"name" => "methods", "value" => "Test Data 2"},
|
18
|
+
"testField" => {"name" => "testField", "value" => "Test Data 3"},
|
19
|
+
"test_field_dash" => {"name" => "test-field-dash", "value" => "Test Data 4"},
|
20
|
+
"test_field_space" => {"name" => "test field space", "value" => "Test Data 5"},
|
21
|
+
"test_field_hash" => {"name" => "test_field_hash", "value" => {"it" => "is a Hash"}},
|
22
|
+
"test_field_array" => {"name" => "test_field_array", "value" => ["Not a hash"]},
|
23
|
+
"test_field_array_with_hash" => {"name" => "test_field_array_with_hash",
|
24
|
+
"value" => [{"try" => "this"}]}
|
25
|
+
}
|
26
|
+
@parsed_class = ParserMock.new(@parsed_data)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "raises an error when a hash is not passed in" do
|
30
|
+
lambda { ParserMock.new }.should raise_error(ArgumentError)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "creates a hash to store data from the fields internally" do
|
34
|
+
@parsed_class.instance_variable_get("@jiralicious_field_parser_data").
|
35
|
+
should be_instance_of(Hash)
|
36
|
+
end
|
37
|
+
|
38
|
+
context "defining methods" do
|
39
|
+
it "defines getter methods on the object it's called in" do
|
40
|
+
@parsed_class.testfield.should == "Test Data"
|
41
|
+
end
|
42
|
+
|
43
|
+
it "prefixes a defined method with jira_ when the method already exists" do
|
44
|
+
@parsed_class.jira_methods.should == "Test Data 2"
|
45
|
+
end
|
46
|
+
|
47
|
+
it "downcases java idiom method names" do
|
48
|
+
@parsed_class.test_field.should == "Test Data 3"
|
49
|
+
end
|
50
|
+
|
51
|
+
it "converts nonword to underscore" do
|
52
|
+
@parsed_class.test_field_dash.should == "Test Data 4"
|
53
|
+
@parsed_class.test_field_space.should == "Test Data 5"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "mashifying data" do
|
58
|
+
it "makes hashes a mash" do
|
59
|
+
@parsed_class.test_field_hash.should be_instance_of(Hashie::Mash)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "recursively makes array elements mashes" do
|
63
|
+
@parsed_class.test_field_array_with_hash.
|
64
|
+
first.should be_instance_of(Hashie::Mash)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "leaves array data alone when it's not a hash" do
|
68
|
+
@parsed_class.test_field_array.should == ["Not a hash"]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
{
|
2
|
+
"expand": "html",
|
3
|
+
"self": "http://example.com:8080/jira/rest/api/2.0/issue/EX-1",
|
4
|
+
"key": "EX-1",
|
5
|
+
"fields": {
|
6
|
+
"sub-tasks": {
|
7
|
+
"name": "sub-tasks",
|
8
|
+
"type": "issuelinks",
|
9
|
+
"value": [
|
10
|
+
{
|
11
|
+
"issueKey": "EX-2",
|
12
|
+
"issue": "http://example.com:8080/jira/rest/api/2.0/issue/EX-2",
|
13
|
+
"type": {
|
14
|
+
"name": "Sub-task",
|
15
|
+
"direction": "OUTBOUND"
|
16
|
+
}
|
17
|
+
}
|
18
|
+
]
|
19
|
+
},
|
20
|
+
"timetracking": {
|
21
|
+
"name": "timetracking",
|
22
|
+
"type": "timetracking",
|
23
|
+
"value": {
|
24
|
+
"timeoriginalestimate": 10,
|
25
|
+
"timeestimate": 3,
|
26
|
+
"timespent": 6
|
27
|
+
}
|
28
|
+
},
|
29
|
+
"project": {
|
30
|
+
"name": "project",
|
31
|
+
"type": "com.atlassian.jira.project.Project",
|
32
|
+
"value": {
|
33
|
+
"self": "http://www.example.com/jira/rest/api/2.0/project/EX",
|
34
|
+
"key": "EX",
|
35
|
+
"name": "Example"
|
36
|
+
}
|
37
|
+
},
|
38
|
+
"updated": {
|
39
|
+
"name": "updated",
|
40
|
+
"type": "java.util.Date",
|
41
|
+
"value": 1
|
42
|
+
},
|
43
|
+
"description": {
|
44
|
+
"name": "description",
|
45
|
+
"type": "java.lang.String",
|
46
|
+
"value": "example bug report"
|
47
|
+
},
|
48
|
+
"links": {
|
49
|
+
"name": "links",
|
50
|
+
"type": "issuelinks",
|
51
|
+
"value": [
|
52
|
+
{
|
53
|
+
"issueKey": "PRJ-2",
|
54
|
+
"issue": "http://example.com:8080/jira/rest/api/2.0/issue/PRJ-2",
|
55
|
+
"type": {
|
56
|
+
"name": "Dependent",
|
57
|
+
"direction": "OUTBOUND",
|
58
|
+
"description": "depends on"
|
59
|
+
}
|
60
|
+
},
|
61
|
+
{
|
62
|
+
"issueKey": "PRJ-3",
|
63
|
+
"issue": "http://example.com:8080/jira/rest/api/2.0/issue/PRJ-3",
|
64
|
+
"type": {
|
65
|
+
"name": "Dependent",
|
66
|
+
"direction": "INBOUND",
|
67
|
+
"description": "is depended by"
|
68
|
+
}
|
69
|
+
}
|
70
|
+
]
|
71
|
+
},
|
72
|
+
"attachment": {
|
73
|
+
"name": "attachment",
|
74
|
+
"type": "attachment",
|
75
|
+
"value": [
|
76
|
+
{
|
77
|
+
"self": "http://www.example.com/jira/rest/api/2.0/attachments/10000",
|
78
|
+
"filename": "picture.jpg",
|
79
|
+
"author": {
|
80
|
+
"self": "http://www.example.com/jira/rest/api/2.0/user?username=fred",
|
81
|
+
"name": "fred",
|
82
|
+
"displayName": "Fred F. User",
|
83
|
+
"active": false
|
84
|
+
},
|
85
|
+
"created": "2011-07-25T06:31:08.307-0500",
|
86
|
+
"size": 23123,
|
87
|
+
"mimeType": "image/jpeg",
|
88
|
+
"content": "http://www.example.com/jira/attachments/10000",
|
89
|
+
"thumbnail": "http://www.example.com/jira/secure/thumbnail/10000"
|
90
|
+
}
|
91
|
+
]
|
92
|
+
},
|
93
|
+
"watcher": {
|
94
|
+
"name": "watcher",
|
95
|
+
"type": "watcher",
|
96
|
+
"value": {
|
97
|
+
"self": "http://www.example.com/jira/rest/api/2.0/issue/EX-1/watchers",
|
98
|
+
"isWatching": false,
|
99
|
+
"watchCount": 1,
|
100
|
+
"watchers": [
|
101
|
+
{
|
102
|
+
"self": "http://www.example.com/jira/rest/api/2.0/user?username=fred",
|
103
|
+
"name": "fred",
|
104
|
+
"displayName": "Fred F. User",
|
105
|
+
"active": false
|
106
|
+
}
|
107
|
+
]
|
108
|
+
}
|
109
|
+
},
|
110
|
+
"comment": {
|
111
|
+
"name": "comment",
|
112
|
+
"type": "java.lang.String",
|
113
|
+
"value": [
|
114
|
+
{
|
115
|
+
"self": "http://example.com:8080/jira/rest/api/2.0/comment/10000",
|
116
|
+
"author": {
|
117
|
+
"self": "http://www.example.com/jira/rest/api/2.0/user?username=fred",
|
118
|
+
"name": "fred",
|
119
|
+
"displayName": "Fred F. User",
|
120
|
+
"active": false
|
121
|
+
},
|
122
|
+
"body": "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.",
|
123
|
+
"updateAuthor": {
|
124
|
+
"self": "http://www.example.com/jira/rest/api/2.0/user?username=fred",
|
125
|
+
"name": "fred",
|
126
|
+
"displayName": "Fred F. User",
|
127
|
+
"active": false
|
128
|
+
},
|
129
|
+
"created": "2011-07-25T06:31:08.311-0500",
|
130
|
+
"updated": "2011-07-25T06:31:08.311-0500",
|
131
|
+
"visibility": {
|
132
|
+
"type": "ROLE",
|
133
|
+
"value": "Administrators"
|
134
|
+
}
|
135
|
+
}
|
136
|
+
]
|
137
|
+
},
|
138
|
+
"worklog": {
|
139
|
+
"name": "worklog",
|
140
|
+
"type": "worklog",
|
141
|
+
"value": [
|
142
|
+
{
|
143
|
+
"self": "http://www.example.com/jira/rest/api/2.0/worklog/10000",
|
144
|
+
"author": {
|
145
|
+
"self": "http://www.example.com/jira/rest/api/2.0/user?username=fred",
|
146
|
+
"name": "fred",
|
147
|
+
"displayName": "Fred F. User",
|
148
|
+
"active": false
|
149
|
+
},
|
150
|
+
"updateAuthor": {
|
151
|
+
"self": "http://www.example.com/jira/rest/api/2.0/user?username=fred",
|
152
|
+
"name": "fred",
|
153
|
+
"displayName": "Fred F. User",
|
154
|
+
"active": false
|
155
|
+
},
|
156
|
+
"comment": "I did some work here.",
|
157
|
+
"visibility": {
|
158
|
+
"type": "GROUP",
|
159
|
+
"value": "jira-developers"
|
160
|
+
},
|
161
|
+
"started": "2011-07-25T06:31:08.314-0500",
|
162
|
+
"minutesSpent": 180
|
163
|
+
}
|
164
|
+
]
|
165
|
+
}
|
166
|
+
}
|
167
|
+
}
|
@@ -0,0 +1,65 @@
|
|
1
|
+
{
|
2
|
+
"2": {
|
3
|
+
"name": "Close Issue",
|
4
|
+
"fields": [{
|
5
|
+
"id": "resolution",
|
6
|
+
"required": true,
|
7
|
+
"type": "com.atlassian.jira.issue.resolution.Resolution"
|
8
|
+
},
|
9
|
+
{
|
10
|
+
"id": "fixVersions",
|
11
|
+
"required": false,
|
12
|
+
"type": "com.atlassian.jira.project.version.Version"
|
13
|
+
},
|
14
|
+
{
|
15
|
+
"id": "customfield_10105",
|
16
|
+
"required": false,
|
17
|
+
"type": "com.atlassian.jira.plugins.jira-importers-plugin:bug-importid"
|
18
|
+
},
|
19
|
+
{
|
20
|
+
"id": "customfield_10106",
|
21
|
+
"required": false,
|
22
|
+
"type": "com.atlassian.jira.plugin.system.customfieldtypes:textfield"
|
23
|
+
},
|
24
|
+
{
|
25
|
+
"id": "assignee",
|
26
|
+
"required": false,
|
27
|
+
"type": "com.opensymphony.user.User"
|
28
|
+
}],
|
29
|
+
"transitionDestination": "6"
|
30
|
+
},
|
31
|
+
"4": {
|
32
|
+
"name": "Start Progress",
|
33
|
+
"fields": [],
|
34
|
+
"transitionDestination": "3"
|
35
|
+
},
|
36
|
+
"5": {
|
37
|
+
"name": "Resolve Issue",
|
38
|
+
"fields": [{
|
39
|
+
"id": "resolution",
|
40
|
+
"required": true,
|
41
|
+
"type": "com.atlassian.jira.issue.resolution.Resolution"
|
42
|
+
},
|
43
|
+
{
|
44
|
+
"id": "fixVersions",
|
45
|
+
"required": false,
|
46
|
+
"type": "com.atlassian.jira.project.version.Version"
|
47
|
+
},
|
48
|
+
{
|
49
|
+
"id": "customfield_10105",
|
50
|
+
"required": false,
|
51
|
+
"type": "com.atlassian.jira.plugins.jira-importers-plugin:bug-importid"
|
52
|
+
},
|
53
|
+
{
|
54
|
+
"id": "customfield_10106",
|
55
|
+
"required": false,
|
56
|
+
"type": "com.atlassian.jira.plugin.system.customfieldtypes:textfield"
|
57
|
+
},
|
58
|
+
{
|
59
|
+
"id": "assignee",
|
60
|
+
"required": false,
|
61
|
+
"type": "com.opensymphony.user.User"
|
62
|
+
}],
|
63
|
+
"transitionDestination": "5"
|
64
|
+
}
|
65
|
+
}
|
data/spec/issue_spec.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
3
|
+
|
4
|
+
describe Jiralicious::Issue, "finding" do
|
5
|
+
|
6
|
+
before :each do
|
7
|
+
Jiralicious.configure do |config|
|
8
|
+
config.username = "jstewart"
|
9
|
+
config.password = "topsecret"
|
10
|
+
config.uri = "http://localhost"
|
11
|
+
config.api_version = "latest"
|
12
|
+
end
|
13
|
+
|
14
|
+
FakeWeb.register_uri(:get,
|
15
|
+
"#{Jiralicious.rest_path}/issue/EX-1",
|
16
|
+
:status => "200",
|
17
|
+
:body => issue_json)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "finds the issue by key" do
|
21
|
+
Jiralicious::Issue.find("EX-1").should be_instance_of(Jiralicious::Issue)
|
22
|
+
issue = Jiralicious::Issue.find("EX-1")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "raises an exception when the issue can't be found or can't be viewed" do
|
26
|
+
lambda {
|
27
|
+
FakeWeb.register_uri(:get,
|
28
|
+
"#{Jiralicious.rest_path}/issue/EX-1",
|
29
|
+
:status => ["404" "Not Found"])
|
30
|
+
Jiralicious::Issue.find("EX-1")
|
31
|
+
}.should raise_error(Jiralicious::IssueNotFound)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "translates the JSON properly" do
|
35
|
+
issue = Jiralicious::Issue.find("EX-1")
|
36
|
+
issue.jira_key.should == "EX-1"
|
37
|
+
issue.jira_self.should == "http://example.com:8080/jira/rest/api/2.0/issue/EX-1"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
describe Jiralicious::Issue, "transitions" do
|
43
|
+
|
44
|
+
before :each do
|
45
|
+
Jiralicious.configure do |config|
|
46
|
+
config.username = "jstewart"
|
47
|
+
config.password = "topsecret"
|
48
|
+
config.uri = "http://localhost"
|
49
|
+
config.api_version = "latest"
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
it "returns list of possible transitions" do
|
55
|
+
FakeWeb.register_uri(:get,
|
56
|
+
"#{Jiralicious.rest_path}/issue/EX-1/transitions",
|
57
|
+
:status => "200",
|
58
|
+
:body => transitions_json)
|
59
|
+
|
60
|
+
transitions = Jiralicious::Issue.get_transitions("#{Jiralicious.rest_path}/issue/EX-1/transitions")
|
61
|
+
transitions.should be_instance_of(Hash)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "performs transition" do
|
65
|
+
FakeWeb.register_uri(:post,
|
66
|
+
"#{Jiralicious.rest_path}/issue/EX-1/transitions",
|
67
|
+
:status => "204",
|
68
|
+
:body => nil)
|
69
|
+
|
70
|
+
result = Jiralicious::Issue.transition("#{Jiralicious.rest_path}/issue/EX-1/transitions",
|
71
|
+
{"transition" => "3", "fields" => []})
|
72
|
+
result.should be_empty
|
73
|
+
end
|
74
|
+
|
75
|
+
it "raises an exception on transition failure" do
|
76
|
+
FakeWeb.register_uri(:post,
|
77
|
+
"#{Jiralicious.rest_path}/issue/EX-1/transitions",
|
78
|
+
:status => "400",
|
79
|
+
:body => %q{{"errorMessages":["Workflow operation is not valid"],"errors":{}}})
|
80
|
+
lambda {
|
81
|
+
result = Jiralicious::Issue.transition("#{Jiralicious.rest_path}/issue/EX-1/transitions",
|
82
|
+
{"transition" => "invalid"})
|
83
|
+
}.should raise_error(Jiralicious::TransitionError)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "raises an IssueNotFound exception if issue is not found" do
|
87
|
+
FakeWeb.register_uri(:post,
|
88
|
+
"#{Jiralicious.rest_path}/issue/EX-1/transitions",
|
89
|
+
:status => "404",
|
90
|
+
:body => %q{{"errorMessages":["Issue Does Not Exist"],"errors":{}}})
|
91
|
+
lambda {
|
92
|
+
result = Jiralicious::Issue.transition("#{Jiralicious.rest_path}/issue/EX-1/transitions",
|
93
|
+
{"transition" => "invalid"})
|
94
|
+
}.should raise_error(Jiralicious::IssueNotFound)
|
95
|
+
end
|
96
|
+
end
|