jira-ruby 0.1.17 → 0.1.18
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +7 -2
- data/Guardfile +14 -0
- data/README.rdoc +7 -2
- data/Rakefile +5 -1
- data/example.rb +23 -1
- data/lib/jira.rb +2 -0
- data/lib/jira/base.rb +5 -4
- data/lib/jira/base_factory.rb +2 -2
- data/lib/jira/client.rb +19 -2
- data/lib/jira/resource/createmeta.rb +52 -0
- data/lib/jira/resource/field.rb +74 -1
- data/lib/jira/resource/issue.rb +22 -5
- data/lib/jira/resource/webhook.rb +40 -0
- data/lib/jira/version.rb +1 -1
- data/spec/integration/webhook.rb +34 -0
- data/spec/jira/base_spec.rb +5 -2
- data/spec/jira/resource/createmeta_spec.rb +253 -0
- data/spec/jira/resource/field_spec.rb +132 -0
- data/spec/jira/resource/issue_spec.rb +21 -1
- data/spec/mock_responses/jira/rest/webhooks/1.0/webhook.json +11 -0
- data/spec/mock_responses/jira/rest/webhooks/1.0/webhook/2.json +11 -0
- data/spec/mock_responses/webhook.json +11 -0
- data/spec/mock_responses/webhook/webhook.json +11 -0
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a295ea67b7236d11b1696c74e9491f80f694c698
|
4
|
+
data.tar.gz: c00568c1bba25ed92d64531df36539ba8d7d3d31
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0e4c24dffaa5d308386ab2698391a8c0c73de5ac67582360c15df32c99775b07495776b6ab87637b0b4ccdb7d47e80508f868c5073391946ea199858fef0a12c
|
7
|
+
data.tar.gz: 89f26829c1937b26846e6557b0265e693e65ff22e764ebdfd05e06209d15034d42ca865846fc048907f06844896fa7b197b7bdd082b1acb564f3e6a969c20eb0
|
data/Gemfile
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
group :development do
|
4
|
+
gem 'guard'
|
5
|
+
gem 'guard-rspec'
|
6
|
+
gem 'pry' # this was in the original Gemfile - but only needed in development
|
7
|
+
gem 'wdm', '>= 0.1.0' if Gem.win_platform?
|
8
|
+
end
|
9
|
+
|
5
10
|
# Specify your gem's dependencies in jira_api.gemspec
|
6
11
|
gemspec
|
data/Guardfile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
gem 'wdm', '>= 0.1.0' if Gem.win_platform?
|
2
|
+
gem 'rspec', '~> 3.0.0'
|
3
|
+
|
4
|
+
guard 'rspec', cmd: 'bundle exec rspec --color --format doc' do
|
5
|
+
# watch /lib/ files
|
6
|
+
watch(%r{^lib/(.+).rb$}) do |m|
|
7
|
+
"spec/#{m[1]}_spec.rb"
|
8
|
+
end
|
9
|
+
|
10
|
+
# watch /spec/ files
|
11
|
+
watch(%r{^spec/(.+).rb$}) do |m|
|
12
|
+
"spec/#{m[1]}.rb"
|
13
|
+
end
|
14
|
+
end
|
data/README.rdoc
CHANGED
@@ -76,6 +76,10 @@ defaults to HTTP Basic Auth.
|
|
76
76
|
Using HTTP Basic Authentication, configure and connect a client to your instance
|
77
77
|
of JIRA.
|
78
78
|
|
79
|
+
Note: If your Jira install is hosted on {atlassian.net}[atlassian.net], it will have no context
|
80
|
+
path by default. If you're having issues connecting, try setting context_path
|
81
|
+
to an empty string in the options hash.
|
82
|
+
|
79
83
|
require 'rubygems'
|
80
84
|
require 'pp'
|
81
85
|
require 'jira'
|
@@ -273,7 +277,8 @@ Here's the same example as a Sinatra application:
|
|
273
277
|
# Initiates the OAuth dance by first requesting a token then redirecting to
|
274
278
|
# http://<yourserver>/auth to get the @access_token
|
275
279
|
get '/signin' do
|
276
|
-
|
280
|
+
callback_url = "#{request.base_url}/callback"
|
281
|
+
request_token = @jira_client.request_token(oauth_callback: callback_url)
|
277
282
|
session[:request_token] = request_token.token
|
278
283
|
session[:request_secret] = request_token.secret
|
279
284
|
|
@@ -283,7 +288,7 @@ Here's the same example as a Sinatra application:
|
|
283
288
|
# http://<yourserver>/callback
|
284
289
|
# Retrieves the @access_token then stores it inside a session cookie. In a real app,
|
285
290
|
# you'll want to persist the token in a datastore associated with the user.
|
286
|
-
get "/callback
|
291
|
+
get "/callback" do
|
287
292
|
request_token = @jira_client.set_request_token(
|
288
293
|
session[:request_token], session[:request_secret]
|
289
294
|
)
|
data/Rakefile
CHANGED
@@ -19,7 +19,11 @@ task :prepare do
|
|
19
19
|
end
|
20
20
|
|
21
21
|
desc 'Run RSpec tests'
|
22
|
-
RSpec::Core::RakeTask.new(:spec)
|
22
|
+
#RSpec::Core::RakeTask.new(:spec)
|
23
|
+
RSpec::Core::RakeTask.new(:spec) do |task|
|
24
|
+
task.rspec_opts = ['--color', '--format', 'doc']
|
25
|
+
end
|
26
|
+
|
23
27
|
|
24
28
|
Rake::RDocTask.new(:doc) do |rd|
|
25
29
|
rd.main = 'README.rdoc'
|
data/example.rb
CHANGED
@@ -42,6 +42,28 @@ end
|
|
42
42
|
issue = client.Issue.find('SAMPLEPROJECT-1')
|
43
43
|
pp issue
|
44
44
|
|
45
|
+
# # Handling fields by name, rather than by id
|
46
|
+
# # ------------------------------------------
|
47
|
+
# Cache the Field list from the server
|
48
|
+
client.Field.map_fields
|
49
|
+
# This allows use of friendlier names for custom fields
|
50
|
+
# Say that 'Special Field' is customfield_12345
|
51
|
+
# It becomes mapped to Special_Field which is usable as a method call
|
52
|
+
#
|
53
|
+
# Say that there is a second 'Special Field' is customfield_54321
|
54
|
+
# Names are deduplicated so the second 'Special Field' becomes Special_Field_54321
|
55
|
+
#
|
56
|
+
# Names are massaged to get rid of special characters, and spaces
|
57
|
+
# So 'Special & @ Field' becomes Special_____Field - not perfect, but usable
|
58
|
+
old_way = issue.customfield_12345
|
59
|
+
new_way = issue.Special_Field
|
60
|
+
(old_way == new_way) && puts 'much easier'
|
61
|
+
#
|
62
|
+
# Can also use this to specify fields to be returned in the response
|
63
|
+
client.Issue.jql(a_normal_jql_search, fields:[:Special_Field])
|
64
|
+
# Or you could always do it the old way - if you can remember the numbers...
|
65
|
+
client.Issue.jql(a_normal_jql_search, fields:['customfield_12345'])
|
66
|
+
|
45
67
|
# # Find a specific project by key
|
46
68
|
# # ------------------------------
|
47
69
|
# project = client.Project.find('SAMPLEPROJECT')
|
@@ -173,4 +195,4 @@ remote_link.save(
|
|
173
195
|
:title => issue_1.key,
|
174
196
|
}
|
175
197
|
}
|
176
|
-
)
|
198
|
+
)
|
data/lib/jira.rb
CHANGED
@@ -30,6 +30,8 @@ require 'jira/resource/filter'
|
|
30
30
|
require 'jira/resource/field'
|
31
31
|
require 'jira/resource/rapidview'
|
32
32
|
require 'jira/resource/serverinfo'
|
33
|
+
require 'jira/resource/createmeta'
|
34
|
+
require 'jira/resource/webhook'
|
33
35
|
|
34
36
|
require 'jira/request_client'
|
35
37
|
require 'jira/oauth_client'
|
data/lib/jira/base.rb
CHANGED
@@ -348,7 +348,7 @@ module JIRA
|
|
348
348
|
# JIRA::HTTPError if the request fails (response is not HTTP 2xx).
|
349
349
|
def save!(attrs)
|
350
350
|
http_method = new_record? ? :post : :put
|
351
|
-
response = client.send(http_method, url, attrs.to_json)
|
351
|
+
response = client.send(http_method, new_record? ? url : patched_url, attrs.to_json)
|
352
352
|
set_attrs(attrs, false)
|
353
353
|
set_attrs_from_response(response)
|
354
354
|
@expanded = false
|
@@ -439,6 +439,7 @@ module JIRA
|
|
439
439
|
end
|
440
440
|
|
441
441
|
# This method fixes issue that there is no / prefix in url. It is happened when we call for instance
|
442
|
+
# Looks like this issue is actual only in case if you use atlassian sdk your app path is not root (like /jira in example below)
|
442
443
|
# issue.save() for existing resource.
|
443
444
|
# As a result we got error 400 from JIRA API:
|
444
445
|
# [07/Jun/2015:15:32:19 +0400] "PUT jira/rest/api/2/issue/10111 HTTP/1.1" 400 -
|
@@ -446,7 +447,7 @@ module JIRA
|
|
446
447
|
# [07/Jun/2015:15:17:18 +0400] "PUT /jira/rest/api/2/issue/10111 HTTP/1.1" 204 -
|
447
448
|
def patched_url
|
448
449
|
result = url
|
449
|
-
result if result.start_with?('/')
|
450
|
+
return result if result.start_with?('/')
|
450
451
|
"/#{result}"
|
451
452
|
end
|
452
453
|
|
@@ -455,8 +456,8 @@ module JIRA
|
|
455
456
|
end
|
456
457
|
|
457
458
|
# Returns a JSON representation of the current attributes hash.
|
458
|
-
def to_json
|
459
|
-
attrs.to_json
|
459
|
+
def to_json(options = {})
|
460
|
+
attrs.to_json(options)
|
460
461
|
end
|
461
462
|
|
462
463
|
# Determines if the resource is newly created by checking whether its
|
data/lib/jira/base_factory.rb
CHANGED
@@ -15,7 +15,7 @@ module JIRA
|
|
15
15
|
# Need to do a little bit of work here as Module.const_get doesn't work
|
16
16
|
# with nested class names, i.e. JIRA::Resource::Foo.
|
17
17
|
#
|
18
|
-
# So create a method chain from the class
|
18
|
+
# So create a method chain from the class components. This code will
|
19
19
|
# unroll to:
|
20
20
|
# Module.const_get('JIRA').const_get('Resource').const_get('Foo')
|
21
21
|
#
|
@@ -35,7 +35,7 @@ module JIRA
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
# The
|
38
|
+
# The principle purpose of this class is to delegate methods to the corresponding
|
39
39
|
# non-factory class and automatically prepend the client argument to the argument
|
40
40
|
# list.
|
41
41
|
delegate_to_target_class :all, :find, :collection_path, :singular_path, :jql
|
data/lib/jira/client.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'json'
|
2
2
|
require 'forwardable'
|
3
|
+
require 'ostruct'
|
3
4
|
|
4
5
|
module JIRA
|
5
6
|
|
@@ -37,7 +38,7 @@ module JIRA
|
|
37
38
|
#
|
38
39
|
# The authenticated client instance returned by the respective client type
|
39
40
|
# (Oauth, Basic)
|
40
|
-
attr_accessor :consumer, :request_client
|
41
|
+
attr_accessor :consumer, :request_client, :http_debug, :cache
|
41
42
|
|
42
43
|
# The configuration options for this client instance
|
43
44
|
attr_reader :options
|
@@ -50,7 +51,8 @@ module JIRA
|
|
50
51
|
:rest_base_path => "/rest/api/2",
|
51
52
|
:ssl_verify_mode => OpenSSL::SSL::VERIFY_PEER,
|
52
53
|
:use_ssl => true,
|
53
|
-
:auth_type => :oauth
|
54
|
+
:auth_type => :oauth,
|
55
|
+
:http_debug => false
|
54
56
|
}
|
55
57
|
|
56
58
|
def initialize(options={})
|
@@ -64,9 +66,15 @@ module JIRA
|
|
64
66
|
@consumer = @request_client.consumer
|
65
67
|
when :basic
|
66
68
|
@request_client = HttpClient.new(@options)
|
69
|
+
else
|
70
|
+
raise ArgumentError, 'Options: ":auth_type" must be ":oauth" or ":basic"'
|
67
71
|
end
|
68
72
|
|
73
|
+
@http_debug = @options[:http_debug]
|
74
|
+
|
69
75
|
@options.freeze
|
76
|
+
|
77
|
+
@cache = OpenStruct.new
|
70
78
|
end
|
71
79
|
|
72
80
|
def Project # :nodoc:
|
@@ -133,10 +141,18 @@ module JIRA
|
|
133
141
|
JIRA::Resource::ServerInfoFactory.new(self)
|
134
142
|
end
|
135
143
|
|
144
|
+
def Createmeta
|
145
|
+
JIRA::Resource::CreatemetaFactory.new(self)
|
146
|
+
end
|
147
|
+
|
136
148
|
def ApplicationLink
|
137
149
|
JIRA::Resource::ApplicationLinkFactory.new(self)
|
138
150
|
end
|
139
151
|
|
152
|
+
def Webhook
|
153
|
+
JIRA::Resource::WebhookFactory.new(self)
|
154
|
+
end
|
155
|
+
|
140
156
|
def Issuelink
|
141
157
|
JIRA::Resource::IssuelinkFactory.new(self)
|
142
158
|
end
|
@@ -176,6 +192,7 @@ module JIRA
|
|
176
192
|
# Sends the specified HTTP request to the REST API through the
|
177
193
|
# appropriate method (oauth, basic).
|
178
194
|
def request(http_method, path, body = '', headers={})
|
195
|
+
puts "#{http_method}: #{path} - [#{body}]" if @http_debug
|
179
196
|
@request_client.request(http_method, path, body, headers)
|
180
197
|
end
|
181
198
|
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module JIRA
|
2
|
+
module Resource
|
3
|
+
|
4
|
+
class CreatemetaFactory < JIRA::BaseFactory # :nodoc:
|
5
|
+
end
|
6
|
+
|
7
|
+
class Createmeta < JIRA::Base
|
8
|
+
def self.endpoint_name
|
9
|
+
'/issue/createmeta'
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.all(client, params={})
|
13
|
+
|
14
|
+
if params.has_key?(:projectKeys)
|
15
|
+
values = Array(params[:projectKeys]).map{|i| (i.is_a?(JIRA::Resource::Project) ? i.key : i)}
|
16
|
+
params[:projectKeys] = values.join(',')
|
17
|
+
end
|
18
|
+
|
19
|
+
if params.has_key?(:projectIds)
|
20
|
+
values = Array(params[:projectIds]).map{|i| (i.is_a?(JIRA::Resource::Project) ? i.id : i)}
|
21
|
+
params[:projectIds] = values.join(',')
|
22
|
+
end
|
23
|
+
|
24
|
+
if params.has_key?(:issuetypeNames)
|
25
|
+
values = Array(params[:issuetypeNames]).map{|i| (i.is_a?(JIRA::Resource::Issuetype) ? i.name : i)}
|
26
|
+
params[:issuetypeNames] = values.join(',')
|
27
|
+
end
|
28
|
+
|
29
|
+
if params.has_key?(:issuetypeIds)
|
30
|
+
values = Array(params[:issuetypeIds]).map{|i| (i.is_a?(JIRA::Resource::Issuetype) ? i.id : i)}
|
31
|
+
params[:issuetypeIds] = values.join(',')
|
32
|
+
end
|
33
|
+
|
34
|
+
create_meta_url = client.options[:rest_base_path] + self.endpoint_name
|
35
|
+
params = hash_to_query_string(params)
|
36
|
+
|
37
|
+
response = params.empty? ? client.get("#{create_meta_url}") : client.get("#{create_meta_url}?#{params}")
|
38
|
+
|
39
|
+
json = parse_json(response.body)
|
40
|
+
self.new(client, {:attrs => json['projects']})
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.hash_to_query_string(query_params)
|
44
|
+
query_params.map do |k,v|
|
45
|
+
CGI.escape(k.to_s) + '=' + CGI.escape(v.to_s)
|
46
|
+
end.join('&')
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
data/lib/jira/resource/field.rb
CHANGED
@@ -2,9 +2,82 @@ module JIRA
|
|
2
2
|
module Resource
|
3
3
|
|
4
4
|
class FieldFactory < JIRA::BaseFactory # :nodoc:
|
5
|
+
delegate_to_target_class :map_fields, :name_to_id, :field_map
|
5
6
|
end
|
6
7
|
|
7
|
-
class Field < JIRA::Base
|
8
|
+
class Field < JIRA::Base
|
8
9
|
|
10
|
+
#translate a custom field description to a method-safe name
|
11
|
+
def self.safe_name(description)
|
12
|
+
description.gsub(/[^a-zA-Z0-9]/,'_')
|
13
|
+
end
|
14
|
+
|
15
|
+
# safe_name plus disambiguation if it fails it uses the original jira id (customfield_#####)
|
16
|
+
def self.safer_name(description, jira_id)
|
17
|
+
"#{safe_name(description)}_#{jira_id.split('_')[1]}" rescue jira_id
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.map_fields(client)
|
21
|
+
field_map = {}
|
22
|
+
field_map_reverse = {}
|
23
|
+
fields = client.Field.all
|
24
|
+
|
25
|
+
# two pass approach, so that a custom field with the same name
|
26
|
+
# as a system field can't take precedence
|
27
|
+
fields.each do |f|
|
28
|
+
next if f.custom
|
29
|
+
name = safe_name(f.name)
|
30
|
+
field_map_reverse[f.id] = [f.name, name] # capture both the official name, and the mapped name
|
31
|
+
field_map[name] = f.id
|
32
|
+
end
|
33
|
+
|
34
|
+
fields.each do |f|
|
35
|
+
next unless f.custom
|
36
|
+
name = if field_map.key? f.name
|
37
|
+
renamed = safer_name(f.name, f.id)
|
38
|
+
warn "Duplicate Field name #{f.name} #{f.id} - renaming as #{renamed}"
|
39
|
+
renamed
|
40
|
+
else
|
41
|
+
safe_name(f.name)
|
42
|
+
end
|
43
|
+
field_map_reverse[f.id] = [f.name, name] # capture both the official name, and the mapped name
|
44
|
+
field_map[name] = f.id
|
45
|
+
end
|
46
|
+
|
47
|
+
client.cache.field_map_reverse = field_map_reverse # not sure where this will be used yet, but sure to be useful
|
48
|
+
client.cache.field_map = field_map
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.field_map(client)
|
52
|
+
client.cache.field_map
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.name_to_id(client, field_name)
|
56
|
+
field_name = field_name.to_s
|
57
|
+
return field_name unless client.cache.field_map && client.cache.field_map[field_name]
|
58
|
+
client.cache.field_map[field_name]
|
59
|
+
end
|
60
|
+
|
61
|
+
def respond_to?(method_name, include_all=false)
|
62
|
+
if [method_name.to_s, client.Field.name_to_id(method_name)].any? {|k| attrs.key?(k)}
|
63
|
+
true
|
64
|
+
else
|
65
|
+
super(method_name)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def method_missing(method_name, *args, &block)
|
70
|
+
if attrs.keys.include?(method_name.to_s)
|
71
|
+
attrs[method_name.to_s]
|
72
|
+
else
|
73
|
+
official_name=client.Field.name_to_id(method_name)
|
74
|
+
if attrs.keys.include?(official_name)
|
75
|
+
attrs[official_name]
|
76
|
+
else
|
77
|
+
super(method_name, *args, &block)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
9
82
|
end
|
10
83
|
end
|
data/lib/jira/resource/issue.rb
CHANGED
@@ -51,7 +51,7 @@ module JIRA
|
|
51
51
|
def self.jql(client, jql, options = {fields: nil, start_at: nil, max_results: nil, expand: nil})
|
52
52
|
url = client.options[:rest_base_path] + "/search?jql=" + CGI.escape(jql)
|
53
53
|
|
54
|
-
url << "&fields=#{options[:fields].map{ |value| CGI.escape(value
|
54
|
+
url << "&fields=#{options[:fields].map{ |value| CGI.escape(client.Field.name_to_id(value)) }.join(',')}" if options[:fields]
|
55
55
|
url << "&startAt=#{CGI.escape(options[:start_at].to_s)}" if options[:start_at]
|
56
56
|
url << "&maxResults=#{CGI.escape(options[:max_results].to_s)}" if options[:max_results]
|
57
57
|
|
@@ -67,8 +67,16 @@ module JIRA
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
+
def editmeta
|
71
|
+
editmeta_url = client.options[:rest_base_path] + "/#{self.class.endpoint_name}/#{key}/editmeta"
|
72
|
+
|
73
|
+
response = client.get(editmeta_url)
|
74
|
+
json = self.class.parse_json(response.body)
|
75
|
+
json['fields']
|
76
|
+
end
|
77
|
+
|
70
78
|
def respond_to?(method_name, include_all=false)
|
71
|
-
if attrs.keys.include?('fields') && attrs['fields'].
|
79
|
+
if attrs.keys.include?('fields') && [method_name.to_s, client.Field.name_to_id(method_name)].any? {|k| attrs['fields'].key?(k)}
|
72
80
|
true
|
73
81
|
else
|
74
82
|
super(method_name)
|
@@ -76,10 +84,19 @@ module JIRA
|
|
76
84
|
end
|
77
85
|
|
78
86
|
def method_missing(method_name, *args, &block)
|
79
|
-
if attrs.keys.include?('fields')
|
80
|
-
attrs['fields']
|
87
|
+
if attrs.keys.include?('fields')
|
88
|
+
if attrs['fields'].keys.include?(method_name.to_s)
|
89
|
+
attrs['fields'][method_name.to_s]
|
90
|
+
else
|
91
|
+
official_name=client.Field.name_to_id(method_name)
|
92
|
+
if attrs['fields'].keys.include?(official_name)
|
93
|
+
attrs['fields'][official_name]
|
94
|
+
else
|
95
|
+
super(method_name, *args, &block)
|
96
|
+
end
|
97
|
+
end
|
81
98
|
else
|
82
|
-
super(method_name)
|
99
|
+
super(method_name, *args, &block)
|
83
100
|
end
|
84
101
|
end
|
85
102
|
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module JIRA
|
2
|
+
module Resource
|
3
|
+
|
4
|
+
class WebhookFactory < JIRA::BaseFactory # :nodoc:
|
5
|
+
end
|
6
|
+
|
7
|
+
class Webhook < JIRA::Base
|
8
|
+
|
9
|
+
REST_BASE_PATH = '/rest/webhooks/1.0/'
|
10
|
+
|
11
|
+
def self.endpoint_name
|
12
|
+
'webhook'
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.full_url(client)
|
16
|
+
client.options[:context_path] + REST_BASE_PATH
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.collection_path(client, prefix = '/')
|
20
|
+
self.full_url(client) + prefix + self.endpoint_name
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.all(client, options = {})
|
24
|
+
response = client.get(collection_path(client))
|
25
|
+
json = parse_json(response.body)
|
26
|
+
json.map do |attrs|
|
27
|
+
self.new(client, {:attrs => attrs}.merge(options))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# def self.save(options={})
|
32
|
+
# end
|
33
|
+
|
34
|
+
# def self.delete(options={})
|
35
|
+
|
36
|
+
# end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/jira/version.rb
CHANGED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe JIRA::Resource::Webhook do
|
4
|
+
|
5
|
+
with_each_client do |site_url, client|
|
6
|
+
let(:client) { client }
|
7
|
+
let(:site_url) { site_url }
|
8
|
+
|
9
|
+
|
10
|
+
let(:key) { "2" }
|
11
|
+
|
12
|
+
let(:expected_attributes) do
|
13
|
+
{"name"=>"from API", "url"=>"http://localhost:3000/webhooks/1", "excludeBody"=>false, "filters"=>{"issue-related-events-section"=>""}, "events"=>[], "enabled"=>true, "self"=>"http://localhost:2990/jira/rest/webhooks/1.0/webhook/2", "lastUpdatedUser"=>"admin", "lastUpdatedDisplayName"=>"admin", "lastUpdated"=>1453306520188}
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:expected_collection_length) { 1 }
|
17
|
+
|
18
|
+
it_should_behave_like "a resource"
|
19
|
+
it_should_behave_like "a resource with a collection GET endpoint"
|
20
|
+
it_should_behave_like "a resource with a singular GET endpoint"
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
it "returns a collection of components" do
|
25
|
+
|
26
|
+
stub_request(:get, site_url + described_class.singular_path(client, key)).
|
27
|
+
to_return(:status => 200, :body => get_mock_response('webhook/webhook.json'))
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/spec/jira/base_spec.rb
CHANGED
@@ -427,9 +427,12 @@ describe JIRA::Base do
|
|
427
427
|
end
|
428
428
|
|
429
429
|
it "converts to json" do
|
430
|
-
subject.attrs = {
|
431
|
-
|
430
|
+
subject.attrs = { 'foo' => 'bar', 'dead' => 'beef' }
|
432
431
|
expect(subject.to_json).to eq(subject.attrs.to_json)
|
432
|
+
|
433
|
+
h = { 'key' => subject }
|
434
|
+
h_attrs = { 'key' => subject.attrs }
|
435
|
+
expect(h.to_json).to eq(h_attrs.to_json)
|
433
436
|
end
|
434
437
|
|
435
438
|
describe "extract attrs from response" do
|
@@ -0,0 +1,253 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe JIRA::Resource::Createmeta do
|
4
|
+
let(:client) {
|
5
|
+
double(
|
6
|
+
'client',
|
7
|
+
:options => {
|
8
|
+
:rest_base_path => '/jira/rest/api/2'
|
9
|
+
}
|
10
|
+
)
|
11
|
+
}
|
12
|
+
|
13
|
+
let(:response) {
|
14
|
+
double(
|
15
|
+
'response',
|
16
|
+
:body => '{"expand":"projects","projects":[{"self":"http://localhost:2029/rest/api/2/project/TST"}]}'
|
17
|
+
)
|
18
|
+
}
|
19
|
+
|
20
|
+
describe 'general' do
|
21
|
+
it 'should query correct url without parameters' do
|
22
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/issue/createmeta').and_return(response)
|
23
|
+
JIRA::Resource::Createmeta.all(client)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should query correct url with `expand` parameter' do
|
27
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/issue/createmeta?expand=projects.issuetypes.fields').and_return(response)
|
28
|
+
JIRA::Resource::Createmeta.all(client, :expand => 'projects.issuetypes.fields')
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should query correct url with `foo` parameter' do
|
32
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/issue/createmeta?foo=bar').and_return(response)
|
33
|
+
JIRA::Resource::Createmeta.all(client, :foo => 'bar')
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
describe 'projectKeys' do
|
40
|
+
it 'should query correct url when only one `projectKeys` given as string' do
|
41
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/issue/createmeta?projectKeys=PROJECT_1').and_return(response)
|
42
|
+
JIRA::Resource::Createmeta.all(
|
43
|
+
client,
|
44
|
+
:projectKeys => 'PROJECT_1',
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should query correct url when multiple `projectKeys` given as string' do
|
49
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/issue/createmeta?projectKeys=PROJECT_1%2CPROJECT_2').and_return(response)
|
50
|
+
JIRA::Resource::Createmeta.all(
|
51
|
+
client,
|
52
|
+
:projectKeys => ['PROJECT_1', 'PROJECT_2'],
|
53
|
+
)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should query correct url when only one `projectKeys` given as Project' do
|
57
|
+
prj = JIRA::Resource::Project.new(client)
|
58
|
+
allow(prj).to receive(:key).and_return('PRJ')
|
59
|
+
|
60
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/issue/createmeta?projectKeys=PRJ').and_return(response)
|
61
|
+
JIRA::Resource::Createmeta.all(
|
62
|
+
client,
|
63
|
+
:projectKeys => prj,
|
64
|
+
)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should query correct url when multiple `projectKeys` given as Project' do
|
68
|
+
prj_1 = JIRA::Resource::Project.new(client)
|
69
|
+
allow(prj_1).to receive(:key).and_return('PRJ_1')
|
70
|
+
prj_2 = JIRA::Resource::Project.new(client)
|
71
|
+
allow(prj_2).to receive(:key).and_return('PRJ_2')
|
72
|
+
|
73
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/issue/createmeta?projectKeys=PRJ_2%2CPRJ_1').and_return(response)
|
74
|
+
JIRA::Resource::Createmeta.all(
|
75
|
+
client,
|
76
|
+
:projectKeys => [prj_2, prj_1],
|
77
|
+
)
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should query correct url when multiple `projectKeys` given as different types' do
|
81
|
+
prj_5 = JIRA::Resource::Project.new(client)
|
82
|
+
allow(prj_5).to receive(:key).and_return('PRJ_5')
|
83
|
+
|
84
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/issue/createmeta?projectKeys=PROJECT_1%2CPRJ_5').and_return(response)
|
85
|
+
JIRA::Resource::Createmeta.all(
|
86
|
+
client,
|
87
|
+
:projectKeys => ['PROJECT_1', prj_5],
|
88
|
+
)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
describe 'projectIds' do
|
94
|
+
it 'should query correct url when only one `projectIds` given as string' do
|
95
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/issue/createmeta?projectIds=10101').and_return(response)
|
96
|
+
JIRA::Resource::Createmeta.all(
|
97
|
+
client,
|
98
|
+
:projectIds => '10101',
|
99
|
+
)
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'should query correct url when multiple `projectIds` given as string' do
|
103
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/issue/createmeta?projectIds=10101%2C20202').and_return(response)
|
104
|
+
JIRA::Resource::Createmeta.all(
|
105
|
+
client,
|
106
|
+
:projectIds => ['10101', '20202'],
|
107
|
+
)
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'should query correct url when only one `projectIds` given as Project' do
|
111
|
+
prj = JIRA::Resource::Project.new(client)
|
112
|
+
allow(prj).to receive(:id).and_return('30303')
|
113
|
+
|
114
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/issue/createmeta?projectIds=30303').and_return(response)
|
115
|
+
JIRA::Resource::Createmeta.all(
|
116
|
+
client,
|
117
|
+
:projectIds => prj,
|
118
|
+
)
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'should query correct url when multiple `projectIds` given as Project' do
|
122
|
+
prj_1 = JIRA::Resource::Project.new(client)
|
123
|
+
allow(prj_1).to receive(:id).and_return('30303')
|
124
|
+
prj_2 = JIRA::Resource::Project.new(client)
|
125
|
+
allow(prj_2).to receive(:id).and_return('50505')
|
126
|
+
|
127
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/issue/createmeta?projectIds=50505%2C30303').and_return(response)
|
128
|
+
JIRA::Resource::Createmeta.all(
|
129
|
+
client,
|
130
|
+
:projectIds => [prj_2, prj_1],
|
131
|
+
)
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'should query correct url when multiple `projectIds` given as different types' do
|
135
|
+
prj_5 = JIRA::Resource::Project.new(client)
|
136
|
+
allow(prj_5).to receive(:id).and_return('60606')
|
137
|
+
|
138
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/issue/createmeta?projectIds=10101%2C60606').and_return(response)
|
139
|
+
JIRA::Resource::Createmeta.all(
|
140
|
+
client,
|
141
|
+
:projectIds => ['10101', prj_5],
|
142
|
+
)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
describe 'issuetypeNames' do
|
148
|
+
it 'should query correct url when only one `issuetypeNames` given as string' do
|
149
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/issue/createmeta?issuetypeNames=Feature').and_return(response)
|
150
|
+
JIRA::Resource::Createmeta.all(
|
151
|
+
client,
|
152
|
+
:issuetypeNames => 'Feature',
|
153
|
+
)
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'should query correct url when multiple `issuetypeNames` given as string' do
|
157
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/issue/createmeta?issuetypeNames=Feature%2CBug').and_return(response)
|
158
|
+
JIRA::Resource::Createmeta.all(
|
159
|
+
client,
|
160
|
+
:issuetypeNames => ['Feature', 'Bug'],
|
161
|
+
)
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'should query correct url when only one `issuetypeNames` given as Issuetype' do
|
165
|
+
issue_type = JIRA::Resource::Issuetype.new(client)
|
166
|
+
allow(issue_type).to receive(:name).and_return('Epic')
|
167
|
+
|
168
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/issue/createmeta?issuetypeNames=Epic').and_return(response)
|
169
|
+
JIRA::Resource::Createmeta.all(
|
170
|
+
client,
|
171
|
+
:issuetypeNames => issue_type,
|
172
|
+
)
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'should query correct url when multiple `issuetypeNames` given as Issuetype' do
|
176
|
+
issue_type_1 = JIRA::Resource::Issuetype.new(client)
|
177
|
+
allow(issue_type_1).to receive(:name).and_return('Epic')
|
178
|
+
issue_type_2 = JIRA::Resource::Issuetype.new(client)
|
179
|
+
allow(issue_type_2).to receive(:name).and_return('Sub-Task')
|
180
|
+
|
181
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/issue/createmeta?issuetypeNames=Sub-Task%2CEpic').and_return(response)
|
182
|
+
JIRA::Resource::Createmeta.all(
|
183
|
+
client,
|
184
|
+
:issuetypeNames => [issue_type_2, issue_type_1],
|
185
|
+
)
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'should query correct url when multiple `issuetypeNames` given as different types' do
|
189
|
+
issue_type = JIRA::Resource::Issuetype.new(client)
|
190
|
+
allow(issue_type).to receive(:name).and_return('Epic')
|
191
|
+
|
192
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/issue/createmeta?issuetypeNames=Feature%2CEpic').and_return(response)
|
193
|
+
JIRA::Resource::Createmeta.all(
|
194
|
+
client,
|
195
|
+
:issuetypeNames => ['Feature', issue_type],
|
196
|
+
)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
|
201
|
+
describe 'issuetypeIds' do
|
202
|
+
it 'should query correct url when only one `issuetypeIds` given as string' do
|
203
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/issue/createmeta?issuetypeIds=10101').and_return(response)
|
204
|
+
JIRA::Resource::Createmeta.all(
|
205
|
+
client,
|
206
|
+
:issuetypeIds => '10101',
|
207
|
+
)
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'should query correct url when multiple `issuetypeIds` given as string' do
|
211
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/issue/createmeta?issuetypeIds=10101%2C20202').and_return(response)
|
212
|
+
JIRA::Resource::Createmeta.all(
|
213
|
+
client,
|
214
|
+
:issuetypeIds => ['10101', '20202'],
|
215
|
+
)
|
216
|
+
end
|
217
|
+
|
218
|
+
it 'should query correct url when only one `issuetypeIds` given as Issuetype' do
|
219
|
+
issue_type = JIRA::Resource::Issuetype.new(client)
|
220
|
+
allow(issue_type).to receive(:id).and_return('30303')
|
221
|
+
|
222
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/issue/createmeta?issuetypeIds=30303').and_return(response)
|
223
|
+
JIRA::Resource::Createmeta.all(
|
224
|
+
client,
|
225
|
+
:issuetypeIds => issue_type,
|
226
|
+
)
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'should query correct url when multiple `issuetypeIds` given as Issuetype' do
|
230
|
+
issue_type_1 = JIRA::Resource::Issuetype.new(client)
|
231
|
+
allow(issue_type_1).to receive(:id).and_return('30303')
|
232
|
+
issue_type_2 = JIRA::Resource::Issuetype.new(client)
|
233
|
+
allow(issue_type_2).to receive(:id).and_return('50505')
|
234
|
+
|
235
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/issue/createmeta?issuetypeIds=50505%2C30303').and_return(response)
|
236
|
+
JIRA::Resource::Createmeta.all(
|
237
|
+
client,
|
238
|
+
:issuetypeIds => [issue_type_2, issue_type_1],
|
239
|
+
)
|
240
|
+
end
|
241
|
+
|
242
|
+
it 'should query correct url when multiple `issuetypeIds` given as different types' do
|
243
|
+
issue_type = JIRA::Resource::Issuetype.new(client)
|
244
|
+
allow(issue_type).to receive(:id).and_return('30303')
|
245
|
+
|
246
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/issue/createmeta?issuetypeIds=10101%2C30303').and_return(response)
|
247
|
+
JIRA::Resource::Createmeta.all(
|
248
|
+
client,
|
249
|
+
:issuetypeIds => ['10101', issue_type],
|
250
|
+
)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe JIRA::Resource::Field do
|
4
|
+
|
5
|
+
let(:cache) { OpenStruct.new }
|
6
|
+
|
7
|
+
let(:client) do
|
8
|
+
client = double(options: {rest_base_path: '/jira/rest/api/2'} )
|
9
|
+
field = JIRA::Resource::FieldFactory.new(client)
|
10
|
+
allow(client).to receive(:Field).and_return(field)
|
11
|
+
allow(client).to receive(:cache).and_return(cache)
|
12
|
+
# info about all fields on the client
|
13
|
+
allow(client.Field).to receive(:all).and_return([
|
14
|
+
JIRA::Resource::Field.new(client, :attrs => {'id' =>"customfield_10666", "name" => "Priority", "custom" => true, "orderable" => true, "navigable" => true, "searchable" => true, "clauseNames" => ["cf[10666]","Priority"], "schema" =>{"type" => "string", "custom" => "com.atlassian.jira.plugin.system.customfieldtypes:select","customId" => 10666}}),
|
15
|
+
JIRA::Resource::Field.new(client, :attrs => {'id' =>"issuekey", "name" => "Key", "custom" => false, "orderable" => false, "navigable" => true, "searchable" => false, "clauseNames" => ["id","issue","issuekey","key"]}),
|
16
|
+
JIRA::Resource::Field.new(client, :attrs => {"id" =>"priority", "name" => "Priority", "custom" => false, "orderable" => true, "navigable" => true, "searchable" => true, "clauseNames" => ["priority"], "schema" =>{"type" => "priority", "system" => "priority"}}),
|
17
|
+
JIRA::Resource::Field.new(client, :attrs => {'id' =>"summary", "name" => "Summary", "custom" => false, "orderable" => true, "navigable" => true, "searchable" => true, "clauseNames" => ["summary"], "schema" =>{"type" => "string", "system" => "summary"}}),
|
18
|
+
JIRA::Resource::Field.new(client, :attrs => {'id' =>"issuetype", "name" => "Issue Type", "custom" => false, "orderable" => true, "navigable" => true, "searchable" => true, "clauseNames" => ["issuetype","type"], "schema" =>{"type" => "issuetype", "system" => "issuetype"}}),
|
19
|
+
JIRA::Resource::Field.new(client, :attrs => {'id' =>"customfield_10111", "name" => "SingleWord", "custom" => true, "orderable" => true, "navigable" => true, "searchable" => true, "clauseNames" => ["cf[10111]","SingleWord"], "schema" =>{"type" => "string", "custom" => "com.atlassian.jira.plugin.system.customfieldtypes:select","customId" => 10111}}),
|
20
|
+
JIRA::Resource::Field.new(client, :attrs => {'id' =>"customfield_10222", "name" => "Multi Word", "custom" => true, "orderable" => true, "navigable" => true, "searchable" => true, "clauseNames" => ["cf[10222]","Multi Word"], "schema" =>{"type" => "string", "custom" => "com.atlassian.jira.plugin.system.customfieldtypes:select","customId" => 10222}}),
|
21
|
+
JIRA::Resource::Field.new(client, :attrs => {'id' =>"customfield_10333", "name" => "Why/N@t", "custom" => true, "orderable" => true, "navigable" => true, "searchable" => true, "clauseNames" => ["cf[10333]","Why/N@t"], "schema" =>{"type" => "string", "custom" => "com.atlassian.jira.plugin.system.customfieldtypes:select","customId" => 10333}}),
|
22
|
+
JIRA::Resource::Field.new(client, :attrs => {'id' =>"customfield_10444", "name" => "SingleWord", "custom" => true, "orderable" => true, "navigable" => true, "searchable" => true, "clauseNames" => ["cf[10444]","SingleWord"], "schema" =>{"type" => "string", "custom" => "com.atlassian.jira.plugin.system.customfieldtypes:select","customId" => 10444}})
|
23
|
+
])
|
24
|
+
client
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "field_mappings" do
|
28
|
+
|
29
|
+
shared_context "mapped or not" do
|
30
|
+
|
31
|
+
subject {
|
32
|
+
JIRA::Resource::Field.new(client, :attrs => {
|
33
|
+
'priority' => 1,
|
34
|
+
'customfield_10111' => 'data_in_custom_field',
|
35
|
+
'customfield_10222' => 'multi word custom name',
|
36
|
+
'customfield_10333' => 'complex custom name',
|
37
|
+
'customfield_10444' => 'duplicated custom name',
|
38
|
+
'customfield_10666' => 'duplicate of a system name',
|
39
|
+
})
|
40
|
+
}
|
41
|
+
|
42
|
+
it "can find a standard field by id" do
|
43
|
+
expect(subject.priority).to eq(1)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "can find a custom field by customfield_##### name" do
|
47
|
+
expect(subject.customfield_10111).to eq('data_in_custom_field')
|
48
|
+
end
|
49
|
+
|
50
|
+
it "is not confused by common attribute keys" do
|
51
|
+
expect{subject.name}.to raise_error(NoMethodError)
|
52
|
+
expect{subject.custom}.to raise_error(NoMethodError)
|
53
|
+
expect(subject.id).to eq(nil) # picks up ID from the parent -
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "before fields are mapped" do
|
58
|
+
|
59
|
+
include_context "mapped or not"
|
60
|
+
|
61
|
+
it "can find a standard field by id" do
|
62
|
+
expect(subject.priority).to eq(1)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "cannot find a standard field by name before mapping" do
|
66
|
+
expect{subject.Priority}.to raise_error(NoMethodError)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "can find a custom field by customfield_##### name" do
|
70
|
+
expect(subject.customfield_10111).to eq('data_in_custom_field')
|
71
|
+
end
|
72
|
+
|
73
|
+
it "cannot find a mapped field before mapping and raises error" do
|
74
|
+
expect{subject.SingleWork}.to raise_error(NoMethodError)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "is not confused by common attribute keys and raises error" do
|
78
|
+
expect{subject.name}.to raise_error(NoMethodError)
|
79
|
+
expect{subject.custom}.to raise_error(NoMethodError)
|
80
|
+
expect(subject.id).to eq(nil) # picks up ID from the parent -
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context "after fields are mapped" do
|
85
|
+
|
86
|
+
before do
|
87
|
+
silence_stream(STDERR) do
|
88
|
+
expect(client.Field.map_fields.class).to eq(Hash)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
include_context "mapped or not"
|
93
|
+
|
94
|
+
it "warns of duplicate fields" do
|
95
|
+
expect{client.Field.map_fields}.to output(/renaming as Priority_10666/).to_stderr
|
96
|
+
expect{client.Field.map_fields}.to output(/renaming as SingleWord_10444/).to_stderr
|
97
|
+
end
|
98
|
+
|
99
|
+
it "can find a mapped field after mapping and returns results" do
|
100
|
+
expect{subject.SingleWord}.to_not raise_error
|
101
|
+
expect(subject.SingleWord).to eq subject.customfield_10111
|
102
|
+
end
|
103
|
+
|
104
|
+
it "handles duplicate names in a safe fashion" do
|
105
|
+
expect{subject.Multi_Word}.to_not raise_error
|
106
|
+
expect(subject.Multi_Word).to eq subject.customfield_10222
|
107
|
+
end
|
108
|
+
|
109
|
+
it "handles special characters in a safe fashion" do
|
110
|
+
expect{subject.Why_N_t}.to_not raise_error
|
111
|
+
expect(subject.Why_N_t).to eq subject.customfield_10333
|
112
|
+
end
|
113
|
+
|
114
|
+
it "handles duplicates in custom names" do
|
115
|
+
expect{subject.SingleWord_10444}.to_not raise_error
|
116
|
+
expect(subject.SingleWord_10444).to eq subject.customfield_10444
|
117
|
+
end
|
118
|
+
|
119
|
+
it "keeps custom names from overwriting system names" do
|
120
|
+
#expect(client.Field.map_fields.class).to eq(Hash)
|
121
|
+
expect{subject.Priority_10666}.to_not raise_error
|
122
|
+
expect(subject.Priority_10666).to eq subject.customfield_10666
|
123
|
+
end
|
124
|
+
|
125
|
+
it "can find a standard field by an expanded name" do
|
126
|
+
#expect(client.Field.map_fields.class).to eq(Hash)
|
127
|
+
expect(subject.priority).to eq(1)
|
128
|
+
expect(subject.Priority).to eq(1)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -5,7 +5,12 @@ describe JIRA::Resource::Issue do
|
|
5
5
|
class JIRAResourceDelegation < SimpleDelegator # :nodoc:
|
6
6
|
end
|
7
7
|
|
8
|
-
let(:client)
|
8
|
+
let(:client) do
|
9
|
+
client = double(options: {rest_base_path: '/jira/rest/api/2'} )
|
10
|
+
allow(client).to receive(:Field).and_return(JIRA::Resource::FieldFactory.new(client))
|
11
|
+
allow(client).to receive(:cache).and_return(OpenStruct.new)
|
12
|
+
client
|
13
|
+
end
|
9
14
|
|
10
15
|
describe "#respond_to?" do
|
11
16
|
describe "when decorated by SimpleDelegator" do
|
@@ -128,6 +133,21 @@ describe JIRA::Resource::Issue do
|
|
128
133
|
expect(JIRA::Resource::Issue.jql(client,'foo bar', expand: %w(transitions))).to eq([''])
|
129
134
|
end
|
130
135
|
|
136
|
+
it 'should return meta data available for editing an issue' do
|
137
|
+
subject = JIRA::Resource::Issue.new(client, :attrs => {'fields' => {'key' =>'TST=123'}})
|
138
|
+
response = double()
|
139
|
+
|
140
|
+
allow(response).to receive(:body).and_return(
|
141
|
+
'{"fields":{"summary":{"required":true,"name":"Summary","operations":["set"]}}}'
|
142
|
+
)
|
143
|
+
expect(client).to receive(:get)
|
144
|
+
.with('/jira/rest/api/2/issue/TST=123/editmeta')
|
145
|
+
.and_return(response)
|
146
|
+
|
147
|
+
expect(subject.editmeta).to eq({'summary' => {'required' => true, 'name' => 'Summary', 'operations' => ['set']}})
|
148
|
+
end
|
149
|
+
|
150
|
+
|
131
151
|
it "provides direct accessors to the fields" do
|
132
152
|
subject = JIRA::Resource::Issue.new(client, :attrs => {'fields' => {'foo' =>'bar'}})
|
133
153
|
expect(subject).to respond_to(:foo)
|
@@ -0,0 +1,11 @@
|
|
1
|
+
[{"name":"from API",
|
2
|
+
"url":"http://localhost:3000/webhooks/1",
|
3
|
+
"excludeBody":false,
|
4
|
+
"filters":{"issue-related-events-section":""},
|
5
|
+
"events":[],
|
6
|
+
"enabled":true,
|
7
|
+
"self":"http://localhost:2990/jira/rest/webhooks/1.0/webhook/2",
|
8
|
+
"lastUpdatedUser":"admin",
|
9
|
+
"lastUpdatedDisplayName":"admin",
|
10
|
+
"lastUpdated":1453306520188
|
11
|
+
}]
|
@@ -0,0 +1,11 @@
|
|
1
|
+
{"name":"from API",
|
2
|
+
"url":"http://localhost:3000/webhooks/1",
|
3
|
+
"excludeBody":false,
|
4
|
+
"filters":{"issue-related-events-section":""},
|
5
|
+
"events":[],
|
6
|
+
"enabled":true,
|
7
|
+
"self":"http://localhost:2990/jira/rest/webhooks/1.0/webhook/2",
|
8
|
+
"lastUpdatedUser":"admin",
|
9
|
+
"lastUpdatedDisplayName":"admin",
|
10
|
+
"lastUpdated":1453306520188
|
11
|
+
}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
[{"name":"from API",
|
2
|
+
"url":"http://localhost:3000/webhooks/1",
|
3
|
+
"excludeBody":false,
|
4
|
+
"filters":{"issue-related-events-section":""},
|
5
|
+
"events":[],
|
6
|
+
"enabled":true,
|
7
|
+
"self":"http://localhost:2990/jira/rest/webhooks/1.0/webhook/2",
|
8
|
+
"lastUpdatedUser":"admin",
|
9
|
+
"lastUpdatedDisplayName":"admin",
|
10
|
+
"lastUpdated":1453306520188}
|
11
|
+
]
|
@@ -0,0 +1,11 @@
|
|
1
|
+
{"name":"from API",
|
2
|
+
"url":"http://localhost:3000/webhooks/1",
|
3
|
+
"excludeBody":false,
|
4
|
+
"filters":{"issue-related-events-section":""},
|
5
|
+
"events":[],
|
6
|
+
"enabled":true,
|
7
|
+
"self":"http://localhost:2990/jira/rest/webhooks/1.0/webhook/2",
|
8
|
+
"lastUpdatedUser":"admin",
|
9
|
+
"lastUpdatedDisplayName":"admin",
|
10
|
+
"lastUpdated":1453306520188
|
11
|
+
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jira-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.18
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- SUMO Heavy Industries
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-04-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|
@@ -103,6 +103,7 @@ files:
|
|
103
103
|
- ".gitignore"
|
104
104
|
- ".travis.yml"
|
105
105
|
- Gemfile
|
106
|
+
- Guardfile
|
106
107
|
- LICENSE.txt
|
107
108
|
- README.rdoc
|
108
109
|
- Rakefile
|
@@ -123,6 +124,7 @@ files:
|
|
123
124
|
- lib/jira/resource/attachment.rb
|
124
125
|
- lib/jira/resource/comment.rb
|
125
126
|
- lib/jira/resource/component.rb
|
127
|
+
- lib/jira/resource/createmeta.rb
|
126
128
|
- lib/jira/resource/field.rb
|
127
129
|
- lib/jira/resource/filter.rb
|
128
130
|
- lib/jira/resource/issue.rb
|
@@ -138,6 +140,7 @@ files:
|
|
138
140
|
- lib/jira/resource/transition.rb
|
139
141
|
- lib/jira/resource/user.rb
|
140
142
|
- lib/jira/resource/version.rb
|
143
|
+
- lib/jira/resource/webhook.rb
|
141
144
|
- lib/jira/resource/worklog.rb
|
142
145
|
- lib/jira/tasks.rb
|
143
146
|
- lib/jira/version.rb
|
@@ -156,6 +159,7 @@ files:
|
|
156
159
|
- spec/integration/transition_spec.rb
|
157
160
|
- spec/integration/user_spec.rb
|
158
161
|
- spec/integration/version_spec.rb
|
162
|
+
- spec/integration/webhook.rb
|
159
163
|
- spec/integration/worklog_spec.rb
|
160
164
|
- spec/jira/base_factory_spec.rb
|
161
165
|
- spec/jira/base_spec.rb
|
@@ -166,6 +170,8 @@ files:
|
|
166
170
|
- spec/jira/oauth_client_spec.rb
|
167
171
|
- spec/jira/request_client_spec.rb
|
168
172
|
- spec/jira/resource/attachment_spec.rb
|
173
|
+
- spec/jira/resource/createmeta_spec.rb
|
174
|
+
- spec/jira/resource/field_spec.rb
|
169
175
|
- spec/jira/resource/filter_spec.rb
|
170
176
|
- spec/jira/resource/issue_spec.rb
|
171
177
|
- spec/jira/resource/issuelink_spec.rb
|
@@ -198,6 +204,8 @@ files:
|
|
198
204
|
- spec/mock_responses/issueLinkType/10000.json
|
199
205
|
- spec/mock_responses/issuetype.json
|
200
206
|
- spec/mock_responses/issuetype/5.json
|
207
|
+
- spec/mock_responses/jira/rest/webhooks/1.0/webhook.json
|
208
|
+
- spec/mock_responses/jira/rest/webhooks/1.0/webhook/2.json
|
201
209
|
- spec/mock_responses/priority.json
|
202
210
|
- spec/mock_responses/priority/1.json
|
203
211
|
- spec/mock_responses/project.json
|
@@ -214,6 +222,8 @@ files:
|
|
214
222
|
- spec/mock_responses/version/10000.invalid.put.json
|
215
223
|
- spec/mock_responses/version/10000.json
|
216
224
|
- spec/mock_responses/version/10000.put.json
|
225
|
+
- spec/mock_responses/webhook.json
|
226
|
+
- spec/mock_responses/webhook/webhook.json
|
217
227
|
- spec/spec_helper.rb
|
218
228
|
- spec/support/clients_helper.rb
|
219
229
|
- spec/support/matchers/have_attributes.rb
|
@@ -259,6 +269,7 @@ test_files:
|
|
259
269
|
- spec/integration/transition_spec.rb
|
260
270
|
- spec/integration/user_spec.rb
|
261
271
|
- spec/integration/version_spec.rb
|
272
|
+
- spec/integration/webhook.rb
|
262
273
|
- spec/integration/worklog_spec.rb
|
263
274
|
- spec/jira/base_factory_spec.rb
|
264
275
|
- spec/jira/base_spec.rb
|
@@ -269,6 +280,8 @@ test_files:
|
|
269
280
|
- spec/jira/oauth_client_spec.rb
|
270
281
|
- spec/jira/request_client_spec.rb
|
271
282
|
- spec/jira/resource/attachment_spec.rb
|
283
|
+
- spec/jira/resource/createmeta_spec.rb
|
284
|
+
- spec/jira/resource/field_spec.rb
|
272
285
|
- spec/jira/resource/filter_spec.rb
|
273
286
|
- spec/jira/resource/issue_spec.rb
|
274
287
|
- spec/jira/resource/issuelink_spec.rb
|
@@ -301,6 +314,8 @@ test_files:
|
|
301
314
|
- spec/mock_responses/issueLinkType/10000.json
|
302
315
|
- spec/mock_responses/issuetype.json
|
303
316
|
- spec/mock_responses/issuetype/5.json
|
317
|
+
- spec/mock_responses/jira/rest/webhooks/1.0/webhook.json
|
318
|
+
- spec/mock_responses/jira/rest/webhooks/1.0/webhook/2.json
|
304
319
|
- spec/mock_responses/priority.json
|
305
320
|
- spec/mock_responses/priority/1.json
|
306
321
|
- spec/mock_responses/project.json
|
@@ -317,6 +332,8 @@ test_files:
|
|
317
332
|
- spec/mock_responses/version/10000.invalid.put.json
|
318
333
|
- spec/mock_responses/version/10000.json
|
319
334
|
- spec/mock_responses/version/10000.put.json
|
335
|
+
- spec/mock_responses/webhook.json
|
336
|
+
- spec/mock_responses/webhook/webhook.json
|
320
337
|
- spec/spec_helper.rb
|
321
338
|
- spec/support/clients_helper.rb
|
322
339
|
- spec/support/matchers/have_attributes.rb
|