jira-ruby-dmg 0.1.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.travis.yml +6 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +46 -0
  6. data/README.rdoc +309 -0
  7. data/Rakefile +28 -0
  8. data/example.rb +119 -0
  9. data/http-basic-example.rb +112 -0
  10. data/jira-ruby-dmg.gemspec +28 -0
  11. data/lib/jira/base.rb +497 -0
  12. data/lib/jira/base_factory.rb +49 -0
  13. data/lib/jira/client.rb +165 -0
  14. data/lib/jira/has_many_proxy.rb +43 -0
  15. data/lib/jira/http_client.rb +69 -0
  16. data/lib/jira/http_error.rb +16 -0
  17. data/lib/jira/oauth_client.rb +84 -0
  18. data/lib/jira/railtie.rb +10 -0
  19. data/lib/jira/request_client.rb +18 -0
  20. data/lib/jira/resource/attachment.rb +12 -0
  21. data/lib/jira/resource/comment.rb +14 -0
  22. data/lib/jira/resource/component.rb +10 -0
  23. data/lib/jira/resource/field.rb +10 -0
  24. data/lib/jira/resource/filter.rb +15 -0
  25. data/lib/jira/resource/issue.rb +76 -0
  26. data/lib/jira/resource/issuetype.rb +10 -0
  27. data/lib/jira/resource/priority.rb +10 -0
  28. data/lib/jira/resource/project.rb +31 -0
  29. data/lib/jira/resource/status.rb +10 -0
  30. data/lib/jira/resource/transition.rb +33 -0
  31. data/lib/jira/resource/user.rb +14 -0
  32. data/lib/jira/resource/version.rb +10 -0
  33. data/lib/jira/resource/worklog.rb +16 -0
  34. data/lib/jira/tasks.rb +0 -0
  35. data/lib/jira/version.rb +3 -0
  36. data/lib/jira.rb +33 -0
  37. data/lib/tasks/generate.rake +18 -0
  38. data/spec/integration/attachment_spec.rb +23 -0
  39. data/spec/integration/comment_spec.rb +55 -0
  40. data/spec/integration/component_spec.rb +42 -0
  41. data/spec/integration/field_spec.rb +35 -0
  42. data/spec/integration/issue_spec.rb +94 -0
  43. data/spec/integration/issuetype_spec.rb +26 -0
  44. data/spec/integration/priority_spec.rb +27 -0
  45. data/spec/integration/project_spec.rb +56 -0
  46. data/spec/integration/status_spec.rb +27 -0
  47. data/spec/integration/transition_spec.rb +52 -0
  48. data/spec/integration/user_spec.rb +25 -0
  49. data/spec/integration/version_spec.rb +43 -0
  50. data/spec/integration/worklog_spec.rb +55 -0
  51. data/spec/jira/base_factory_spec.rb +46 -0
  52. data/spec/jira/base_spec.rb +586 -0
  53. data/spec/jira/client_spec.rb +188 -0
  54. data/spec/jira/has_many_proxy_spec.rb +45 -0
  55. data/spec/jira/http_client_spec.rb +109 -0
  56. data/spec/jira/http_error_spec.rb +25 -0
  57. data/spec/jira/oauth_client_spec.rb +111 -0
  58. data/spec/jira/request_client_spec.rb +14 -0
  59. data/spec/jira/resource/attachment_spec.rb +20 -0
  60. data/spec/jira/resource/filter_spec.rb +97 -0
  61. data/spec/jira/resource/issue_spec.rb +107 -0
  62. data/spec/jira/resource/project_factory_spec.rb +13 -0
  63. data/spec/jira/resource/project_spec.rb +70 -0
  64. data/spec/jira/resource/worklog_spec.rb +24 -0
  65. data/spec/mock_responses/attachment/10000.json +20 -0
  66. data/spec/mock_responses/component/10000.invalid.put.json +5 -0
  67. data/spec/mock_responses/component/10000.json +39 -0
  68. data/spec/mock_responses/component/10000.put.json +39 -0
  69. data/spec/mock_responses/component.post.json +28 -0
  70. data/spec/mock_responses/field/1.json +15 -0
  71. data/spec/mock_responses/field.json +32 -0
  72. data/spec/mock_responses/issue/10002/comment/10000.json +29 -0
  73. data/spec/mock_responses/issue/10002/comment/10000.put.json +29 -0
  74. data/spec/mock_responses/issue/10002/comment.json +65 -0
  75. data/spec/mock_responses/issue/10002/comment.post.json +29 -0
  76. data/spec/mock_responses/issue/10002/transitions.json +49 -0
  77. data/spec/mock_responses/issue/10002/transitions.post.json +1 -0
  78. data/spec/mock_responses/issue/10002/worklog/10000.json +31 -0
  79. data/spec/mock_responses/issue/10002/worklog/10000.put.json +30 -0
  80. data/spec/mock_responses/issue/10002/worklog.json +98 -0
  81. data/spec/mock_responses/issue/10002/worklog.post.json +30 -0
  82. data/spec/mock_responses/issue/10002.invalid.put.json +6 -0
  83. data/spec/mock_responses/issue/10002.json +126 -0
  84. data/spec/mock_responses/issue/10002.put.missing_field_update.json +6 -0
  85. data/spec/mock_responses/issue.json +1108 -0
  86. data/spec/mock_responses/issue.post.json +5 -0
  87. data/spec/mock_responses/issuetype/5.json +8 -0
  88. data/spec/mock_responses/issuetype.json +42 -0
  89. data/spec/mock_responses/priority/1.json +8 -0
  90. data/spec/mock_responses/priority.json +42 -0
  91. data/spec/mock_responses/project/SAMPLEPROJECT.issues.json +1108 -0
  92. data/spec/mock_responses/project/SAMPLEPROJECT.json +84 -0
  93. data/spec/mock_responses/project.json +12 -0
  94. data/spec/mock_responses/status/1.json +7 -0
  95. data/spec/mock_responses/status.json +37 -0
  96. data/spec/mock_responses/user_username=admin.json +17 -0
  97. data/spec/mock_responses/version/10000.invalid.put.json +5 -0
  98. data/spec/mock_responses/version/10000.json +11 -0
  99. data/spec/mock_responses/version/10000.put.json +7 -0
  100. data/spec/mock_responses/version.post.json +7 -0
  101. data/spec/spec_helper.rb +22 -0
  102. data/spec/support/clients_helper.rb +16 -0
  103. data/spec/support/matchers/have_attributes.rb +11 -0
  104. data/spec/support/matchers/have_many.rb +9 -0
  105. data/spec/support/matchers/have_one.rb +5 -0
  106. data/spec/support/shared_examples/integration.rb +190 -0
  107. metadata +301 -0
@@ -0,0 +1,43 @@
1
+ #
2
+ # Whenever a collection from a has_many relationship is accessed, an instance
3
+ # of this class is returned. This instance wraps the Array of instances in
4
+ # the collection with an extra build method, which allows new instances to be
5
+ # built on the collection with the correct properties.
6
+ #
7
+ # In practice, instances of this class behave exactly like an Array.
8
+ #
9
+ class JIRA::HasManyProxy
10
+
11
+ attr_reader :target_class, :parent
12
+ attr_accessor :collection
13
+
14
+ def initialize(parent, target_class, collection = [])
15
+ @parent = parent
16
+ @target_class = target_class
17
+ @collection = collection
18
+ end
19
+
20
+ # Builds an instance of this class with the correct parent.
21
+ # For example, issue.comments.build(attrs) will initialize a
22
+ # comment as follows:
23
+ #
24
+ # JIRA::Resource::Comment.new(issue.client,
25
+ # :attrs => attrs,
26
+ # :issue => issue)
27
+ def build(attrs = {})
28
+ resource = target_class.new(parent.client, :attrs => attrs, parent.to_sym => parent)
29
+ collection << resource
30
+ resource
31
+ end
32
+
33
+ # Forces an HTTP request to fetch all instances of the target class that
34
+ # are associated with the parent
35
+ def all
36
+ target_class.all(parent.client, parent.to_sym => parent)
37
+ end
38
+
39
+ # Delegate any missing methods to the collection that this proxy wraps
40
+ def method_missing(method_name, *args, &block)
41
+ collection.send(method_name, *args, &block)
42
+ end
43
+ end
@@ -0,0 +1,69 @@
1
+ require 'json'
2
+ require 'net/https'
3
+ require 'cgi/cookie'
4
+
5
+ module JIRA
6
+ class HttpClient < RequestClient
7
+
8
+ DEFAULT_OPTIONS = {
9
+ :username => '',
10
+ :password => ''
11
+ }
12
+
13
+ attr_reader :options
14
+
15
+ def initialize(options)
16
+ @options = DEFAULT_OPTIONS.merge(options)
17
+ @cookies = {}
18
+ end
19
+
20
+ def make_request(http_method, path, body='', headers={})
21
+ request = Net::HTTP.const_get(http_method.to_s.capitalize).new(path, headers)
22
+ request.body = body unless body.nil?
23
+ add_cookies(request) if options[:use_cookies]
24
+ request.basic_auth(@options[:username], @options[:password])
25
+ response = basic_auth_http_conn.request(request)
26
+ store_cookies(response) if options[:use_cookies]
27
+ response
28
+ end
29
+
30
+ def basic_auth_http_conn
31
+ http_conn(uri)
32
+ end
33
+
34
+ def http_conn(uri)
35
+ if @options[:proxy_address]
36
+ http_class = Net::HTTP::Proxy(@options[:proxy_address], @options[:proxy_port] ? @options[:proxy_port] : 80)
37
+ else
38
+ http_class = Net::HTTP
39
+ end
40
+ http_conn = http_class.new(uri.host, uri.port)
41
+ http_conn.use_ssl = @options[:use_ssl]
42
+ http_conn.verify_mode = @options[:ssl_verify_mode]
43
+ http_conn
44
+ end
45
+
46
+ def uri
47
+ uri = URI.parse(@options[:site])
48
+ end
49
+
50
+ private
51
+
52
+ def store_cookies(response)
53
+ cookies = response.get_fields('set-cookie')
54
+ if cookies
55
+ cookies.each do |cookie|
56
+ data = CGI::Cookie.parse(cookie)
57
+ data.delete('Path')
58
+ @cookies.merge!(data)
59
+ end
60
+ end
61
+ end
62
+
63
+ def add_cookies(request)
64
+ cookie_array = @cookies.values.map { |cookie| cookie.to_s }
65
+ request.add_field('Cookie', cookie_array.join('; ')) if cookie_array.any?
66
+ request
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,16 @@
1
+ require 'forwardable'
2
+ module JIRA
3
+
4
+ class HTTPError < StandardError
5
+ extend Forwardable
6
+
7
+ def_instance_delegators :@response, :message, :code
8
+ attr_reader :response
9
+
10
+ def initialize(response)
11
+ @response = response
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,84 @@
1
+ require 'oauth'
2
+ require 'json'
3
+ require 'forwardable'
4
+
5
+ module JIRA
6
+ class OauthClient < RequestClient
7
+
8
+ DEFAULT_OPTIONS = {
9
+ :signature_method => 'RSA-SHA1',
10
+ :request_token_path => "/plugins/servlet/oauth/request-token",
11
+ :authorize_path => "/plugins/servlet/oauth/authorize",
12
+ :access_token_path => "/plugins/servlet/oauth/access-token",
13
+ :private_key_file => "rsakey.pem",
14
+ :consumer_key => nil,
15
+ :consumer_secret => nil
16
+ }
17
+
18
+ # This exception is thrown when the client is used before the OAuth access token
19
+ # has been initialized.
20
+ class UninitializedAccessTokenError < StandardError
21
+ def message
22
+ "init_access_token must be called before using the client"
23
+ end
24
+ end
25
+
26
+ extend Forwardable
27
+
28
+ attr_accessor :consumer
29
+ attr_reader :options
30
+
31
+ def_instance_delegators :@consumer, :key, :secret, :get_request_token
32
+
33
+ def initialize(options)
34
+ @options = DEFAULT_OPTIONS.merge(options)
35
+ @consumer = init_oauth_consumer(@options)
36
+ end
37
+
38
+ def init_oauth_consumer(options)
39
+ @options[:request_token_path] = @options[:context_path] + @options[:request_token_path]
40
+ @options[:authorize_path] = @options[:context_path] + @options[:authorize_path]
41
+ @options[:access_token_path] = @options[:context_path] + @options[:access_token_path]
42
+ OAuth::Consumer.new(@options[:consumer_key],@options[:consumer_secret],@options)
43
+ end
44
+
45
+ # Returns the current request token if it is set, else it creates
46
+ # and sets a new token.
47
+ def request_token
48
+ @request_token ||= get_request_token
49
+ end
50
+
51
+ # Sets the request token from a given token and secret.
52
+ def set_request_token(token, secret)
53
+ @request_token = OAuth::RequestToken.new(@consumer, token, secret)
54
+ end
55
+
56
+ # Initialises and returns a new access token from the params hash
57
+ # returned by the OAuth transaction.
58
+ def init_access_token(params)
59
+ @access_token = request_token.get_access_token(params)
60
+ end
61
+
62
+ # Sets the access token from a preexisting token and secret.
63
+ def set_access_token(token, secret)
64
+ @access_token = OAuth::AccessToken.new(@consumer, token, secret)
65
+ end
66
+
67
+ # Returns the current access token. Raises an
68
+ # JIRA::Client::UninitializedAccessTokenError exception if it is not set.
69
+ def access_token
70
+ raise UninitializedAccessTokenError.new unless @access_token
71
+ @access_token
72
+ end
73
+
74
+ def make_request(http_method, path, body='', headers={})
75
+ case http_method
76
+ when :delete, :get, :head
77
+ response = access_token.send http_method, path, headers
78
+ when :post, :put
79
+ response = access_token.send http_method, path, body, headers
80
+ end
81
+ response
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,10 @@
1
+ require 'jira'
2
+ require 'rails'
3
+
4
+ module JIRA
5
+ class Railtie < Rails::Railtie
6
+ rake_tasks do
7
+ load 'tasks/generate.rake'
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,18 @@
1
+ require 'oauth'
2
+ require 'json'
3
+ require 'net/https'
4
+
5
+ module JIRA
6
+ class RequestClient
7
+
8
+ # Returns the response if the request was successful (HTTP::2xx) and
9
+ # raises a JIRA::HTTPError if it was not successful, with the response
10
+ # attached.
11
+
12
+ def request(*args)
13
+ response = make_request(*args)
14
+ raise HTTPError.new(response) unless response.kind_of?(Net::HTTPSuccess)
15
+ response
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+ module JIRA
2
+ module Resource
3
+
4
+ class AttachmentFactory < JIRA::BaseFactory # :nodoc:
5
+ end
6
+
7
+ class Attachment < JIRA::Base
8
+ has_one :author, :class => JIRA::Resource::User
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ module JIRA
2
+ module Resource
3
+
4
+ class CommentFactory < JIRA::BaseFactory # :nodoc:
5
+ end
6
+
7
+ class Comment < JIRA::Base
8
+ belongs_to :issue
9
+
10
+ nested_collections true
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ module JIRA
2
+ module Resource
3
+
4
+ class ComponentFactory < JIRA::BaseFactory # :nodoc:
5
+ end
6
+
7
+ class Component < JIRA::Base ; end
8
+
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module JIRA
2
+ module Resource
3
+
4
+ class FieldFactory < JIRA::BaseFactory # :nodoc:
5
+ end
6
+
7
+ class Field < JIRA::Base ; end
8
+
9
+ end
10
+ end
@@ -0,0 +1,15 @@
1
+ module JIRA
2
+ module Resource
3
+ class FilterFactory < JIRA::BaseFactory # :nodoc:
4
+ end
5
+
6
+ class Filter < JIRA::Base
7
+ has_one :owner, :class => JIRA::Resource::User
8
+
9
+ # Returns all the issues for this filter
10
+ def issues
11
+ Issue.jql(self.client, self.jql)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,76 @@
1
+ require 'cgi'
2
+
3
+ module JIRA
4
+ module Resource
5
+
6
+ class IssueFactory < JIRA::BaseFactory # :nodoc:
7
+ end
8
+
9
+ class Issue < JIRA::Base
10
+
11
+ has_one :reporter, :class => JIRA::Resource::User,
12
+ :nested_under => 'fields'
13
+ has_one :assignee, :class => JIRA::Resource::User,
14
+ :nested_under => 'fields'
15
+ has_one :project, :nested_under => 'fields'
16
+
17
+ has_one :issuetype, :nested_under => 'fields'
18
+
19
+ has_one :priority, :nested_under => 'fields'
20
+
21
+ has_one :status, :nested_under => 'fields'
22
+
23
+ has_many :transitions
24
+
25
+ has_many :components, :nested_under => 'fields'
26
+
27
+ has_many :comments, :nested_under => ['fields','comment']
28
+
29
+ has_many :attachments, :nested_under => 'fields',
30
+ :attribute_key => 'attachment'
31
+
32
+ has_many :versions, :nested_under => 'fields'
33
+
34
+ has_many :worklogs, :nested_under => ['fields','worklog']
35
+
36
+ def self.all(client)
37
+ response = client.get(
38
+ client.options[:rest_base_path] + "/search",
39
+ :expand => 'transitions.fields'
40
+ )
41
+ json = parse_json(response.body)
42
+ json['issues'].map do |issue|
43
+ client.Issue.build(issue)
44
+ end
45
+ end
46
+
47
+ def self.jql(client, jql, fields = nil)
48
+ url = client.options[:rest_base_path] + "/search?jql=" + CGI.escape(jql)
49
+ url += CGI.escape("&fields=#{fields.join(",")}") if fields
50
+ response = client.get(url)
51
+ json = parse_json(response.body)
52
+ json['issues'].map do |issue|
53
+ client.Issue.build(issue)
54
+ end
55
+ end
56
+
57
+ def respond_to?(method_name)
58
+ if attrs.keys.include?('fields') && attrs['fields'].keys.include?(method_name.to_s)
59
+ true
60
+ else
61
+ super(method_name)
62
+ end
63
+ end
64
+
65
+ def method_missing(method_name, *args, &block)
66
+ if attrs.keys.include?('fields') && attrs['fields'].keys.include?(method_name.to_s)
67
+ attrs['fields'][method_name.to_s]
68
+ else
69
+ super(method_name)
70
+ end
71
+ end
72
+
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,10 @@
1
+ module JIRA
2
+ module Resource
3
+
4
+ class IssuetypeFactory < JIRA::BaseFactory # :nodoc:
5
+ end
6
+
7
+ class Issuetype < JIRA::Base ; end
8
+
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module JIRA
2
+ module Resource
3
+
4
+ class PriorityFactory < JIRA::BaseFactory # :nodoc:
5
+ end
6
+
7
+ class Priority < JIRA::Base ; end
8
+
9
+ end
10
+ end
@@ -0,0 +1,31 @@
1
+ module JIRA
2
+ module Resource
3
+
4
+ class ProjectFactory < JIRA::BaseFactory # :nodoc:
5
+ end
6
+
7
+ class Project < JIRA::Base
8
+
9
+ has_one :lead, :class => JIRA::Resource::User
10
+ has_many :components
11
+ has_many :issuetypes, :attribute_key => 'issueTypes'
12
+ has_many :versions
13
+
14
+ def self.key_attribute
15
+ :key
16
+ end
17
+
18
+ # Returns all the issues for this project
19
+ def issues(options={})
20
+ search_url = client.options[:rest_base_path] + '/search'
21
+ query_params = {:jql => "project=\"#{key}\""}
22
+ query_params.update Base.query_params_for_search(options)
23
+ response = client.get(url_with_query_params(search_url, query_params))
24
+ json = self.class.parse_json(response.body)
25
+ json['issues'].map do |issue|
26
+ client.Issue.build(issue)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,10 @@
1
+ module JIRA
2
+ module Resource
3
+
4
+ class StatusFactory < JIRA::BaseFactory # :nodoc:
5
+ end
6
+
7
+ class Status < JIRA::Base ; end
8
+
9
+ end
10
+ end
@@ -0,0 +1,33 @@
1
+ module JIRA
2
+ module Resource
3
+
4
+ class TransitionFactory < JIRA::BaseFactory # :nodoc:
5
+ end
6
+
7
+ class Transition < JIRA::Base
8
+ has_one :to, :class => JIRA::Resource::Status
9
+ belongs_to :issue
10
+
11
+ nested_collections true
12
+
13
+ def self.endpoint_name
14
+ 'transitions'
15
+ end
16
+
17
+ def self.all(client, options = {})
18
+ issue = options[:issue]
19
+ unless issue
20
+ raise ArgumentError.new("parent issue is required")
21
+ end
22
+
23
+ path = "#{issue.self}/#{endpoint_name}?expand=transitions.fields"
24
+ response = client.get(path)
25
+ json = parse_json(response.body)
26
+ json['transitions'].map do |transition|
27
+ issue.transitions.build(transition)
28
+ end
29
+ end
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,14 @@
1
+ module JIRA
2
+ module Resource
3
+
4
+ class UserFactory < JIRA::BaseFactory # :nodoc:
5
+ end
6
+
7
+ class User < JIRA::Base
8
+ def self.singular_path(client, key, prefix = '/')
9
+ collection_path(client, prefix) + '?username=' + key
10
+ end
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ module JIRA
2
+ module Resource
3
+
4
+ class VersionFactory < JIRA::BaseFactory # :nodoc:
5
+ end
6
+
7
+ class Version < JIRA::Base ; end
8
+
9
+ end
10
+ end
@@ -0,0 +1,16 @@
1
+ module JIRA
2
+ module Resource
3
+
4
+ class WorklogFactory < JIRA::BaseFactory # :nodoc:
5
+ end
6
+
7
+ class Worklog < JIRA::Base
8
+ has_one :author, :class => JIRA::Resource::User
9
+ has_one :update_author, :class => JIRA::Resource::User,
10
+ :attribute_key => "updateAuthor"
11
+ belongs_to :issue
12
+ nested_collections true
13
+ end
14
+
15
+ end
16
+ end
data/lib/jira/tasks.rb ADDED
File without changes
@@ -0,0 +1,3 @@
1
+ module JIRA
2
+ VERSION = "0.1.10"
3
+ end
data/lib/jira.rb ADDED
@@ -0,0 +1,33 @@
1
+ $: << File.expand_path(File.dirname(__FILE__))
2
+
3
+ require 'active_support/inflector'
4
+ ActiveSupport::Inflector.inflections do |inflector|
5
+ inflector.singular 'status', 'status'
6
+ end
7
+
8
+ require 'jira/base'
9
+ require 'jira/base_factory'
10
+ require 'jira/has_many_proxy'
11
+ require 'jira/http_error'
12
+
13
+ require 'jira/resource/user'
14
+ require 'jira/resource/attachment'
15
+ require 'jira/resource/component'
16
+ require 'jira/resource/issuetype'
17
+ require 'jira/resource/version'
18
+ require 'jira/resource/status'
19
+ require 'jira/resource/transition'
20
+ require 'jira/resource/project'
21
+ require 'jira/resource/priority'
22
+ require 'jira/resource/comment'
23
+ require 'jira/resource/worklog'
24
+ require 'jira/resource/issue'
25
+ require 'jira/resource/filter'
26
+ require 'jira/resource/field'
27
+
28
+ require 'jira/request_client'
29
+ require 'jira/oauth_client'
30
+ require 'jira/http_client'
31
+ require 'jira/client'
32
+
33
+ require 'jira/railtie' if defined?(Rails)
@@ -0,0 +1,18 @@
1
+ require 'securerandom'
2
+
3
+ namespace :jira do
4
+ desc "Generate a consumer key for your application"
5
+ task :generate_consumer_key do
6
+ key = SecureRandom.hex(16)
7
+ puts "You can use this as your consumer key: #{key}"
8
+ end
9
+
10
+ desc "Run the system call to generate a RSA public certificate"
11
+ task :generate_public_cert do
12
+ puts "Executing 'openssl req -x509 -nodes -newkey rsa:1024 -sha1 -keyout rsakey.pem -out rsacert.pem'"
13
+ system('openssl req -x509 -subj "/C=US/ST=New York/L=New York/O=SUMO Heavy Industries/CN=www.sumoheavy.com" -nodes -newkey rsa:1024 -sha1 -keyout rsakey.pem -out rsacert.pem')
14
+ puts "Done. The RSA-SHA1 private keyfile is in the current directory: \'rsakey.pem\'."
15
+ puts "You will need to copy the following certificate into your application link configuration in Jira:"
16
+ system("cat rsacert.pem")
17
+ end
18
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe JIRA::Resource::Attachment do
4
+
5
+ with_each_client do |site_url, client|
6
+ let(:client) { client }
7
+ let(:site_url) { site_url }
8
+
9
+ let(:key) { "10000" }
10
+
11
+ let(:expected_attributes) do
12
+ {
13
+ 'self' => "http://localhost:2990/jira/rest/api/2/attachment/10000",
14
+ 'size' => 15360,
15
+ 'filename' => "ballmer.png"
16
+ }
17
+ end
18
+
19
+ it_should_behave_like "a resource"
20
+ it_should_behave_like "a resource with a singular GET endpoint"
21
+ it_should_behave_like "a resource with a DELETE endpoint"
22
+ end
23
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe JIRA::Resource::Comment do
4
+
5
+ with_each_client do |site_url, client|
6
+ let(:client) { client }
7
+ let(:site_url) { site_url }
8
+
9
+ let(:key) { "10000" }
10
+
11
+ let(:target) { JIRA::Resource::Comment.new(client, :attrs => {'id' => '99999'}, :issue_id => '54321') }
12
+
13
+ let(:expected_collection_length) { 2 }
14
+
15
+ let(:belongs_to) {
16
+ JIRA::Resource::Issue.new(client, :attrs => {
17
+ 'id' => '10002',
18
+ 'fields' => {
19
+ 'comment' => {'comments' => []}
20
+ }
21
+ })
22
+ }
23
+
24
+ let(:expected_attributes) do
25
+ {
26
+ 'self' => "http://localhost:2990/jira/rest/api/2/issue/10002/comment/10000",
27
+ 'id' => key,
28
+ 'body' => "This is a comment. Creative."
29
+ }
30
+ end
31
+
32
+ let(:attributes_for_post) {
33
+ { "body" => "new comment" }
34
+ }
35
+ let(:expected_attributes_from_post) {
36
+ { "id" => "10001", "body" => "new comment"}
37
+ }
38
+
39
+ let(:attributes_for_put) {
40
+ {"body" => "new body"}
41
+ }
42
+ let(:expected_attributes_from_put) {
43
+ { "id" => "10000", "body" => "new body" }
44
+ }
45
+
46
+ it_should_behave_like "a resource"
47
+ it_should_behave_like "a resource with a collection GET endpoint"
48
+ it_should_behave_like "a resource with a singular GET endpoint"
49
+ it_should_behave_like "a resource with a DELETE endpoint"
50
+ it_should_behave_like "a resource with a POST endpoint"
51
+ it_should_behave_like "a resource with a PUT endpoint"
52
+
53
+ end
54
+
55
+ end