jira-ruby 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,44 @@
1
+ module Jira
2
+ module Resource
3
+
4
+ # This is the base class for all the Jira resource factory instances.
5
+ class BaseFactory
6
+
7
+ attr_reader :client
8
+
9
+ def initialize(client)
10
+ @client = client
11
+ end
12
+
13
+ # Return the name of the class which this factory generates, i.e.
14
+ # Jira::Resource::FooFactory creates Jira::Resource::Foo instances.
15
+ def target_class
16
+ # Need to do a little bit of work here as Module.const_get doesn't work
17
+ # with nested class names, i.e. Jira::Resource::Foo.
18
+ #
19
+ # So create a method chain from the class componenets. This code will
20
+ # unroll to:
21
+ # Module.const_get('Jira').const_get('Resource').const_get('Foo')
22
+ #
23
+ target_class_name = self.class.name.sub(/Factory$/, '')
24
+ class_components = target_class_name.split('::')
25
+
26
+ class_components.inject(Module) do |mod, const_name|
27
+ mod.const_get(const_name)
28
+ end
29
+ end
30
+
31
+ def all
32
+ target_class.all(@client)
33
+ end
34
+
35
+ def find(key)
36
+ target_class.find(@client, key)
37
+ end
38
+
39
+ def build(attrs={})
40
+ target_class.build(@client, attrs)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,15 @@
1
+ module Jira
2
+ module Resource
3
+
4
+ class ComponentFactory < BaseFactory ; end
5
+
6
+ class Component < Base
7
+
8
+ def self.key_attribute
9
+ :id
10
+ end
11
+
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ require 'forwardable'
2
+ module Jira
3
+ module Resource
4
+
5
+ class HTTPError < StandardError
6
+ extend Forwardable
7
+
8
+ delegate [:message, :code] => :response
9
+ attr_reader :response
10
+
11
+ def initialize(response)
12
+ @response = response
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ module Jira
2
+ module Resource
3
+
4
+ class IssueFactory < BaseFactory ; end
5
+
6
+ class Issue < Base
7
+
8
+ def self.key_attribute
9
+ :id
10
+ end
11
+
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ module Jira
2
+ module Resource
3
+
4
+ class ProjectFactory < BaseFactory ; end
5
+
6
+ class Project < Base ; end
7
+
8
+ end
9
+ end
data/lib/jira/tasks.rb ADDED
File without changes
@@ -0,0 +1,3 @@
1
+ module Jira
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,16 @@
1
+ namespace :jira do
2
+ desc "Generate a consumer key for your application"
3
+ task :generate_consumer_key do
4
+ #FIXME SERIOUSLY. THIS IS NOT A REAL SOLUTION. I FEEL SO UNCLEAN.
5
+ system("for i in {1..10}; do echo $RANDOM$RANDOM$RANDOM; done | md5 | awk '{ print \"You can use this as your consumer key: \" $0 }'")
6
+ end
7
+
8
+ desc "Run the system call to generate a RSA public certificate"
9
+ task :generate_public_cert do
10
+ puts "Executing 'openssl req -x509 -nodes -newkey rsa:1024 -sha1 -keyout rsakey.pem -out rsacert.pem'"
11
+ system("openssl req -x509 -nodes -newkey rsa:1024 -sha1 -keyout rsakey.pem -out rsacert.pem")
12
+ puts "Done. The RSA-SHA1 private keyfile is in the current directory: \'rsakey.pem\'."
13
+ puts "You will need to copy the following certificate into your application link configuration in Jira:"
14
+ system("cat rsacert.pem")
15
+ end
16
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jira::Resource::Component do
4
+
5
+
6
+ let(:client) do
7
+ client = Jira::Client.new('foo', 'bar')
8
+ client.set_access_token('abc', '123')
9
+ client
10
+ end
11
+
12
+ let(:expected_attributes) do
13
+ {
14
+ 'self' => "http://localhost:2990/jira/rest/api/2/component/10000",
15
+ 'id' => "10000",
16
+ 'name' => "Cheesecake"
17
+ }
18
+ end
19
+
20
+ before(:each) do
21
+ stub_request(:get,
22
+ "http://localhost:2990/jira/rest/api/2/component/10000").
23
+ to_return(:body => get_mock_response('component/10000.json'))
24
+ stub_request(:delete,
25
+ "http://localhost:2990/jira/rest/api/2/component/10000").
26
+ to_return(:body => nil)
27
+ stub_request(:post,
28
+ "http://localhost:2990/jira/rest/api/2/component").
29
+ with(:body => '{"name":"Test component","project":"SAMPLEPROJECT"}').
30
+ to_return(:status => 201, :body => get_mock_response('component.post.json'))
31
+ stub_request(:put,
32
+ "http://localhost:2990/jira/rest/api/2/component/10000").
33
+ with(:body => '{"name":"Jammy"}').
34
+ to_return(:status => 200, :body => get_mock_response('component/10000.put.json'))
35
+ end
36
+
37
+ it "should get a single component by id" do
38
+ component = client.Component.find(10000)
39
+
40
+ component.should have_attributes(expected_attributes)
41
+ end
42
+
43
+ it "builds and fetches single component" do
44
+ component = client.Component.build('id' => 10000)
45
+ component.fetch
46
+
47
+ component.should have_attributes(expected_attributes)
48
+ end
49
+
50
+ it "deletes a component" do
51
+ component = client.Component.build('id' => "10000")
52
+ component.delete.should be_true
53
+ end
54
+
55
+ it "saves a new component" do
56
+ component = client.Component.build
57
+ component.save({"name" => "Test component", "project" => "SAMPLEPROJECT"}).should be_true
58
+ component.id.should == "10001"
59
+ component.name.should == "Test component"
60
+ end
61
+
62
+ it "saves an existing component" do
63
+ component = client.Component.build('id' => '10000')
64
+ component.fetch
65
+ component.save('name' => 'Jammy').should be_true
66
+ component.id.should == "10000"
67
+ component.name.should == "Jammy"
68
+ end
69
+
70
+ end
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jira::Resource::Issue do
4
+
5
+ let(:client) do
6
+ client = Jira::Client.new('foo', 'bar')
7
+ client.set_access_token('abc', '123')
8
+ client
9
+ end
10
+
11
+ let(:expected_attributes) do
12
+ {
13
+ 'self' => "http://localhost:2990/jira/rest/api/2/issue/10002",
14
+ 'key' => "SAMPLEPROJECT-1",
15
+ 'expand' => "renderedFields,names,schema,transitions,editmeta,changelog"
16
+ }
17
+ end
18
+
19
+ before(:each) do
20
+ stub_request(:get,
21
+ "http://localhost:2990/jira/rest/api/2/issue/10002").
22
+ to_return(:body => get_mock_response('issue/10002.json'))
23
+ stub_request(:delete,
24
+ "http://localhost:2990/jira/rest/api/2/issue/10002").
25
+ to_return(:body => nil)
26
+ stub_request(:post, "http://localhost:2990/jira/rest/api/2/issue").
27
+ with(:body => '{"foo":"bar"}').
28
+ to_return(:body => get_mock_response('issue.post.json'))
29
+ stub_request(:put, "http://localhost:2990/jira/rest/api/2/issue/10002").
30
+ with(:body => '{"foo":"bar"}').
31
+ to_return(:body => nil)
32
+ stub_request(:get,
33
+ "http://localhost:2990/jira/rest/api/2/issue/99999").
34
+ to_return(:status => 404, :body => '{"errorMessages":["Issue Does Not Exist"],"errors": {}}')
35
+ end
36
+
37
+ it "should get a single issue by key" do
38
+ issue = client.Issue.find('10002')
39
+
40
+ issue.should have_attributes(expected_attributes)
41
+ end
42
+
43
+ it "should handle issue not found" do
44
+ lambda do
45
+ issue = client.Issue.find('99999')
46
+ end.should raise_exception(Jira::Resource::HTTPError)
47
+ end
48
+
49
+ it "builds and fetches single issue" do
50
+ issue = client.Issue.build('id' => '10002')
51
+ issue.fetch
52
+
53
+ issue.should have_attributes(expected_attributes)
54
+ end
55
+
56
+ it "deletes an issue" do
57
+ issue = client.Issue.build('id' => "10002")
58
+ issue.delete.should be_true
59
+ end
60
+
61
+ it "should save a new record" do
62
+ subject = described_class.new(client)
63
+ subject.save('foo' => 'bar').should be_true
64
+ end
65
+
66
+ it "should save an existing record" do
67
+ subject = client.Issue.build('id' => '10002')
68
+ subject.fetch
69
+ subject.save('foo' => 'bar').should be_true
70
+ end
71
+
72
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jira::Resource::Project do
4
+
5
+ let(:client) do
6
+ client = Jira::Client.new('foo', 'bar')
7
+ client.set_access_token('abc', '123')
8
+ client
9
+ end
10
+
11
+ let(:expected_attributes) do
12
+ {
13
+ 'self' => "http://localhost:2990/jira/rest/api/2/project/SAMPLEPROJECT",
14
+ 'key' => "SAMPLEPROJECT",
15
+ 'name' => "Sample Project for Developing RoR RESTful API"
16
+ }
17
+ end
18
+
19
+ before(:each) do
20
+ stub_request(:get,
21
+ "http://localhost:2990/jira/rest/api/2/project").
22
+ to_return(:body => get_mock_response('project.json'))
23
+ stub_request(:get,
24
+ "http://localhost:2990/jira/rest/api/2/project/SAMPLEPROJECT").
25
+ to_return(:body => get_mock_response('project/SAMPLEPROJECT.json'))
26
+ end
27
+
28
+ it "should get all the projects" do
29
+ projects = client.Project.all
30
+ projects.length.should == 1
31
+
32
+ first = projects.first
33
+ first.should have_attributes(expected_attributes)
34
+ end
35
+
36
+ it "should get a single project by key" do
37
+ project = client.Project.find('SAMPLEPROJECT')
38
+
39
+ project.should have_attributes(expected_attributes)
40
+ end
41
+
42
+ it "builds and fetches single project" do
43
+ project = client.Project.build('key' => 'SAMPLEPROJECT')
44
+ project.fetch
45
+
46
+ project.should have_attributes(expected_attributes)
47
+ end
48
+ end
@@ -0,0 +1,157 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jira::Client do
4
+
5
+ subject {Jira::Client.new('foo','bar')}
6
+
7
+ let(:response) do
8
+ response = mock("response")
9
+ response.stub(:kind_of?).with(Net::HTTPSuccess).and_return(true)
10
+ response
11
+ end
12
+
13
+ it "creates an instance" do
14
+ subject.class.should == Jira::Client
15
+ end
16
+
17
+ it "sets consumer key" do
18
+ subject.key.should == 'foo'
19
+ end
20
+
21
+ it "sets consumer secret" do
22
+ subject.secret.should == 'bar'
23
+ end
24
+
25
+ it "sets the default options" do
26
+ Jira::Client::DEFAULT_OPTIONS.each do |key, value|
27
+ subject.options[key].should == value
28
+ end
29
+ end
30
+
31
+ it "allows the overriding of some options" do
32
+ # Check it overrides a given option ...
33
+ client = Jira::Client.new('foo', 'bar', :site => 'http://foo.com/')
34
+ client.options[:site].should == 'http://foo.com/'
35
+
36
+ # ... but leaves the rest intact
37
+ Jira::Client::DEFAULT_OPTIONS.keys.reject do |key|
38
+ key == :site
39
+ end.each do |key|
40
+ client.options[key].should == Jira::Client::DEFAULT_OPTIONS[key]
41
+ end
42
+
43
+ Jira::Client::DEFAULT_OPTIONS[:site].should_not == 'http://foo.com/'
44
+ end
45
+
46
+ # To avoid having to validate options after initialisation, e.g. setting
47
+ # client.options[:invalid] = 'foo'
48
+ it "freezes the options" do
49
+ subject.options.should be_frozen
50
+ end
51
+
52
+ it "creates a Oauth::Consumer on initialize" do
53
+ subject.consumer.class.should == OAuth::Consumer
54
+ subject.consumer.key.should == subject.key
55
+ subject.consumer.secret.should == subject.secret
56
+ end
57
+
58
+ it "returns an OAuth request_token" do
59
+ # Cannot just check for method delegation as http connection will be attempted
60
+ request_token = OAuth::RequestToken.new(subject.consumer)
61
+ subject.consumer.stub(:get_request_token => request_token)
62
+ subject.get_request_token.should == request_token
63
+ end
64
+
65
+ it "is possible to set the request token" do
66
+ token = mock()
67
+ OAuth::RequestToken.should_receive(:new).with(subject.consumer, 'foo', 'bar').and_return(token)
68
+
69
+ request_token = subject.set_request_token('foo', 'bar')
70
+
71
+ request_token.should == token
72
+ subject.request_token.should == token
73
+ end
74
+
75
+ describe "access token" do
76
+
77
+ it "initializes the access token" do
78
+ request_token = OAuth::RequestToken.new(subject.consumer)
79
+ subject.consumer.stub(:get_request_token => request_token)
80
+ mock_access_token = mock()
81
+ request_token.should_receive(:get_access_token).with(:oauth_verifier => 'abc123').and_return(mock_access_token)
82
+ subject.init_access_token(:oauth_verifier => 'abc123')
83
+ subject.access_token.should == mock_access_token
84
+ end
85
+
86
+ it "raises an exception when accessing without initialisation" do
87
+ lambda do
88
+ subject.access_token
89
+ end.should raise_exception(Jira::Client::UninitializedAccessTokenError, "init_access_token must be called before using the client")
90
+ end
91
+
92
+ it "is possible to set the access token" do
93
+ token = mock()
94
+ OAuth::AccessToken.should_receive(:new).with(subject.consumer, 'foo', 'bar').and_return(token)
95
+
96
+ access_token = subject.set_access_token('foo', 'bar')
97
+
98
+ access_token.should == token
99
+ subject.access_token.should == token
100
+ end
101
+
102
+ end
103
+
104
+ describe "http" do
105
+
106
+ it "responds to the http methods" do
107
+ mock_access_token = mock()
108
+ subject.stub(:access_token => mock_access_token)
109
+ [:delete, :get, :head].each do |method|
110
+ mock_access_token.should_receive(:request).with(method, '/path', {'Accept' => 'application/json'}).and_return(response)
111
+ subject.send(method, '/path')
112
+ end
113
+ [:post, :put].each do |method|
114
+ mock_access_token.should_receive(:request).with(method,
115
+ '/path', '',
116
+ {'Accept' => 'application/json', 'Content-Type' => 'application/json'}).and_return(response)
117
+ subject.send(method, '/path')
118
+ end
119
+ end
120
+
121
+ it "performs a request" do
122
+ access_token = mock()
123
+ access_token.should_receive(:request).with(:get, '/foo').and_return(response)
124
+ subject.stub(:access_token => access_token)
125
+ subject.request(:get, '/foo')
126
+ end
127
+
128
+ it "raises an exception for non success responses" do
129
+ response = mock()
130
+ response.stub(:kind_of?).with(Net::HTTPSuccess).and_return(false)
131
+ access_token = mock()
132
+ access_token.should_receive(:request).with(:get, '/foo').and_return(response)
133
+ subject.stub(:access_token => access_token)
134
+
135
+ lambda do
136
+ subject.request(:get, '/foo')
137
+ end.should raise_exception(Jira::Resource::HTTPError)
138
+ end
139
+
140
+ end
141
+
142
+ describe "Resource Factories" do
143
+
144
+ it "gets all projects" do
145
+ Jira::Resource::Project.should_receive(:all).with(subject).and_return([])
146
+ subject.Project.all.should == []
147
+ end
148
+
149
+ it "finds a single project" do
150
+ find_result = mock()
151
+ Jira::Resource::Project.should_receive(:find).with(subject, '123').and_return(find_result)
152
+ subject.Project.find('123').should == find_result
153
+ end
154
+
155
+ end
156
+
157
+ end