diff --git a/.github/workflows/.rubocop.yml b/.github/workflows/.rubocop.yml new file mode 100644 index 00000000..3bcaa948 --- /dev/null +++ b/.github/workflows/.rubocop.yml @@ -0,0 +1,18 @@ +name: Rubocop + +on: [push, pull_request] + +jobs: + rubocop: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.1' + bundler-cache: true + - name: Run rubocop + run: | + bundle exec rubocop --format github \ No newline at end of file diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 2e1387f7..f86e909b 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -16,7 +16,7 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Setup Ruby + - name: Set up Ruby uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 00000000..67695d6f --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,191 @@ +require: + - rubocop-rspec + +AllCops: + Exclude: + - 'example.rb' + - 'http-basic-example.rb' + - 'vendor/**/*' + NewCops: enable + TargetRubyVersion: 3.1 + +Naming/FileName: + Exclude: + - 'lib/jira-ruby.rb' + +Naming/MethodName: + Enabled: false + +Style/Documentation: + Enabled: false + +Style/FrozenStringLiteralComment: + Exclude: + - 'spec/**/*' + +## +# Temporarily Disable +# +# We are going to disable these and fix in pull requests +## +Layout/ClosingHeredocIndentation: + Enabled: false + +Layout/EmptyLineAfterGuardClause: + Enabled: false + +Layout/EmptyLinesAroundMethodBody: + Enabled: false + +Layout/HashAlignment: + Enabled: false + +Layout/LineLength: + Enabled: false + +Lint/ConstantDefinitionInBlock: + Enabled: false + +Lint/EmptyClass: + Enabled: false + +Lint/IneffectiveAccessModifier: + Enabled: false + +Lint/MissingSuper: + Enabled: false + +Lint/RedundantCopDisableDirective: + Enabled: false + +Lint/UselessAssignment: + Enabled: false + +Metrics/AbcSize: + Enabled: false + +Metrics/ClassLength: + Enabled: false + +Metrics/CyclomaticComplexity: + Enabled: false + +Metrics/MethodLength: + Enabled: false + +Metrics/PerceivedComplexity: + Enabled: false + +Naming/AccessorMethodName: + Enabled: false + +Naming/BlockForwarding: + Enabled: false + +Naming/HeredocDelimiterNaming: + Enabled: false + +Naming/PredicateName: + Enabled: false + +Naming/VariableNumber: + Enabled: false + +RSpec/AnyInstance: + Enabled: false + +RSpec/BeEq: + Enabled: false + +RSpec/ContextWording: + Enabled: false + +RSpec/ExampleLength: + Enabled: false + +RSpec/ExpectInHook: + Enabled: false + +RSpec/FilePath: + Enabled: false + +RSpec/IndexedLet: + Enabled: false + +RSpec/InstanceVariable: + Enabled: false + +RSpec/LeakyConstantDeclaration: + Enabled: false + +RSpec/MessageChain: + Enabled: false + +RSpec/MessageSpies: + Enabled: false + +RSpec/MultipleExpectations: + Enabled: false + +RSpec/MultipleMemoizedHelpers: + Enabled: false + +RSpec/NamedSubject: + Enabled: false + +RSpec/NestedGroups: + Enabled: false + +RSpec/NoExpectationExample: + Enabled: false + +RSpec/PredicateMatcher: + Enabled: false + +RSpec/ReceiveMessages: + Enabled: false + +RSpec/RepeatedSubjectCall: + Enabled: false + +RSpec/SpecFilePathFormat: + Enabled: false + +RSpec/SpecFilePathSuffix: + Enabled: false + +RSpec/StubbedMock: + Enabled: false + +RSpec/SubjectStub: + Enabled: false + +RSpec/VerifiedDoubleReference: + Enabled: false + +RSpec/VerifiedDoubles: + Enabled: false + +Security/Open: + Enabled: false + +Style/ArgumentsForwarding: + Enabled: false + +Style/CaseEquality: + Enabled: false + +Style/ClassAndModuleChildren: + Enabled: false + +Style/MissingRespondToMissing: + Enabled: false + +Style/OpenStructUse: + Enabled: false + +Style/OptionalBooleanParameter: + Enabled: false + +Style/SymbolProc: + Enabled: false \ No newline at end of file diff --git a/Gemfile b/Gemfile index 4912c25c..f22f0f44 100644 --- a/Gemfile +++ b/Gemfile @@ -1,13 +1,21 @@ +# frozen_string_literal: true + source 'https://rubygems.org' group :development do - gem 'guard' - gem 'guard-rspec' + gem 'guard', '~> 2.18', '>= 2.18.1' + gem 'guard-rspec', '~> 4.7', '>= 4.7.3' + gem 'railties' + gem 'rake', '~> 13.2', '>= 13.2.1' + gem 'rspec', '~> 3.0', '>= 3.13' gem 'wdm', '>= 0.1.0' if Gem.win_platform? + gem 'webmock', '~> 3.23', '>= 3.23.0' end group :development, :test do gem 'pry' # this was in the original Gemfile - but only needed in development & test + gem 'rubocop' + gem 'rubocop-rspec', require: false end # Specify your gem's dependencies in jira_api.gemspec diff --git a/Guardfile b/Guardfile index 478391e2..a4442c29 100644 --- a/Guardfile +++ b/Guardfile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + gem 'wdm', '>= 0.1.0' if Gem.win_platform? gem 'rspec', '~> 3.0.0' diff --git a/Rakefile b/Rakefile index cdb06d6f..97702a53 100644 --- a/Rakefile +++ b/Rakefile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'bundler/gem_tasks' require 'rubygems' @@ -13,13 +15,10 @@ task test: %i[prepare spec] desc 'Prepare and run rspec tests' task :prepare do rsa_key = File.expand_path('rsakey.pem') - unless File.exist?(rsa_key) - Rake::Task['jira:generate_public_cert'].invoke - end + Rake::Task['jira:generate_public_cert'].invoke unless File.exist?(rsa_key) end desc 'Run RSpec tests' -# RSpec::Core::RakeTask.new(:spec) RSpec::Core::RakeTask.new(:spec, [] => [:prepare]) do |task| task.rspec_opts = ['--color', '--format', 'doc'] end diff --git a/http-basic-example.rb b/http-basic-example.rb index 41c31b09..4e287832 100644 --- a/http-basic-example.rb +++ b/http-basic-example.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rubygems' require 'pp' require 'jira-ruby' diff --git a/jira-ruby.gemspec b/jira-ruby.gemspec index 70ce734b..f9471627 100644 --- a/jira-ruby.gemspec +++ b/jira-ruby.gemspec @@ -1,3 +1,5 @@ +# frozen_string_literal: true + $LOAD_PATH.push File.expand_path('lib', __dir__) require 'jira/version' @@ -9,27 +11,19 @@ Gem::Specification.new do |s| s.summary = 'Ruby Gem for use with the Atlassian JIRA REST API' s.description = 'API for JIRA' s.licenses = ['MIT'] - s.metadata = { 'source_code_uri' => 'https://github.com/sumoheavy/jira-ruby' } + s.metadata = { + 'source_code_uri' => 'https://github.com/sumoheavy/jira-ruby', + 'rubygems_mfa_required' => 'true' + } s.required_ruby_version = '>= 3.1.0' s.files = `git ls-files`.split("\n") - s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) } s.require_paths = ['lib'] - # Runtime Dependencies s.add_runtime_dependency 'activesupport' s.add_runtime_dependency 'atlassian-jwt' s.add_runtime_dependency 'multipart-post' s.add_runtime_dependency 'oauth', '~> 1.0' - - # Development Dependencies - s.add_development_dependency 'guard', '~> 2.18', '>= 2.18.1' - s.add_development_dependency 'guard-rspec', '~> 4.7', '>= 4.7.3' - s.add_development_dependency 'pry', '~> 0.14', '>= 0.14.3' - s.add_development_dependency 'railties' - s.add_development_dependency 'rake', '~> 13.2', '>= 13.2.1' - s.add_development_dependency 'rspec', '~> 3.0', '>= 3.13' - s.add_development_dependency 'webmock', '~> 3.23', '>= 3.23.0' end diff --git a/lib/jira-ruby.rb b/lib/jira-ruby.rb index addb96c6..a5ccd060 100644 --- a/lib/jira-ruby.rb +++ b/lib/jira-ruby.rb @@ -1,9 +1,11 @@ +# frozen_string_literal: true + $LOAD_PATH << __dir__ require 'active_support' require 'active_support/inflector' ActiveSupport::Inflector.inflections do |inflector| - inflector.singular /status$/, 'status' + inflector.singular(/status$/, 'status') end require 'jira/base' diff --git a/lib/jira/base.rb b/lib/jira/base.rb index 52c6dbf3..2a13fdfa 100644 --- a/lib/jira/base.rb +++ b/lib/jira/base.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'active_support/core_ext/string' require 'active_support/inflector' require 'set' @@ -81,8 +83,8 @@ def initialize(client, options = {}) if options[relation] instance_variable_set("@#{relation}", options[relation]) instance_variable_set("@#{relation}_id", options[relation].key_value) - elsif options["#{relation}_id".to_sym] - instance_variable_set("@#{relation}_id", options["#{relation}_id".to_sym]) + elsif options[:"#{relation}_id"] + instance_variable_set("@#{relation}_id", options[:"#{relation}_id"]) else raise ArgumentError, "Required option #{relation.inspect} missing" unless options[relation] end @@ -96,7 +98,7 @@ def self.all(client, options = {}) json = parse_json(response.body) json = json[endpoint_name.pluralize] if collection_attributes_are_nested json.map do |attrs| - new(client, { attrs: attrs }.merge(options)) + new(client, { attrs: }.merge(options)) end end @@ -111,7 +113,7 @@ def self.find(client, key, options = {}) # Builds a new instance of the resource with the given attributes. # These attributes will be posted to the JIRA Api if save is called. def self.build(client, attrs) - new(client, attrs: attrs) + new(client, attrs:) end # Returns the name of this resource for use in URL components. @@ -141,7 +143,7 @@ def self.collection_path(client, prefix = '/') # JIRA::Resource::Comment.singular_path('456','/issue/123/') # # => /jira/rest/api/2/issue/123/comment/456 def self.singular_path(client, key, prefix = '/') - collection_path(client, prefix) + '/' + key.to_s + "#{collection_path(client, prefix)}/#{key}" end # Returns the attribute name of the attribute used for find. @@ -193,10 +195,11 @@ def self.parse_json(string) # :nodoc: # # => Looks for {"foo":{"bar":{"baz":{"child":{}}}}} def self.has_one(resource, options = {}) attribute_key = options[:attribute_key] || resource.to_s - child_class = options[:class] || ('JIRA::Resource::' + resource.to_s.classify).constantize + child_class = options[:class] || "JIRA::Resource::#{resource.to_s.classify}".constantize define_method(resource) do attribute = maybe_nested_attribute(attribute_key, options[:nested_under]) return nil unless attribute + child_class.new(client, attrs: attribute) end end @@ -244,7 +247,7 @@ def self.has_one(resource, options = {}) # # => Looks for {"foo":{"bar":{"baz":{"children":{}}}}} def self.has_many(collection, options = {}) attribute_key = options[:attribute_key] || collection.to_s - child_class = options[:class] || ('JIRA::Resource::' + collection.to_s.classify).constantize + child_class = options[:class] || "JIRA::Resource::#{collection.to_s.classify}".constantize self_class_basename = name.split('::').last.downcase.to_sym define_method(collection) do child_class_options = { self_class_basename => self } @@ -322,7 +325,7 @@ def collection_path(prefix = '/') # issue it returns '/issue' def path_component path_component = "/#{self.class.endpoint_name}" - path_component += '/' + key_value if key_value + path_component += "/#{key_value}" if key_value path_component end @@ -331,6 +334,7 @@ def path_component # is not set def fetch(reload = false, query_params = {}) return if expanded? && !reload + response = client.get(url_with_query_params(url, query_params)) set_attrs_from_response(response) @expanded = true @@ -359,14 +363,14 @@ def save!(attrs, path = nil) def save(attrs, path = url) begin save_status = save!(attrs, path) - rescue JIRA::HTTPError => exception + rescue JIRA::HTTPError => e begin - set_attrs_from_response(exception.response) # Merge error status generated by JIRA REST API + set_attrs_from_response(e.response) # Merge error status generated by JIRA REST API rescue JSON::ParserError => parse_exception set_attrs('exception' => { - 'class' => exception.response.class.name, - 'code' => exception.response.code, - 'message' => exception.response.message + 'class' => e.response.class.name, + 'code' => e.response.code, + 'message' => e.response.message }) end # raise exception @@ -378,10 +382,10 @@ def save(attrs, path = url) # Sets the attributes hash from a HTTPResponse object from JIRA if it is # not nil or is not a json response. def set_attrs_from_response(response) - unless response.body.nil? || (response.body.length < 2) - json = self.class.parse_json(response.body) - set_attrs(json) - end + return if response.body.nil? || (response.body.length < 2) + json = self.class.parse_json(response.body) + set_attrs(json) + end # Set the current attributes from a hash. If clobber is true, any existing @@ -419,7 +423,7 @@ def url prefix = '/' unless self.class.belongs_to_relationships.empty? prefix = self.class.belongs_to_relationships.inject(prefix) do |prefix_so_far, relationship| - prefix_so_far.to_s + relationship.to_s + '/' + send("#{relationship}_id").to_s + '/' + "#{prefix_so_far}#{relationship}/#{send("#{relationship}_id")}/" end end if @attrs['self'] @@ -434,7 +438,8 @@ def url end # This method fixes issue that there is no / prefix in url. It is happened when we call for instance - # 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) + # Looks like this issue is actual only in case if you use atlassian sdk your app pathis not root + # (like /jira in example below) # issue.save() for existing resource. # As a result we got error 400 from JIRA API: # [07/Jun/2015:15:32:19 +0400] "PUT jira/rest/api/2/issue/10111 HTTP/1.1" 400 - @@ -443,6 +448,7 @@ def url def patched_url result = url return result if result.start_with?('/', 'http') + "/#{result}" end @@ -476,15 +482,18 @@ def maybe_nested_attribute(attribute_name, nested_under = nil) def self.maybe_nested_attribute(attributes, attribute_name, nested_under = nil) return attributes[attribute_name] if nested_under.nil? + if nested_under.instance_of? Array final = nested_under.inject(attributes) do |parent, key| break if parent.nil? + parent[key] end return nil if final.nil? + final[attribute_name] else - return attributes[nested_under][attribute_name] + attributes[nested_under][attribute_name] end end @@ -493,10 +502,10 @@ def url_with_query_params(url, query_params) end def self.url_with_query_params(url, query_params) - if !query_params.empty? - "#{url}?#{hash_to_query_string query_params}" - else + if query_params.empty? url + else + "#{url}?#{hash_to_query_string query_params}" end end @@ -506,20 +515,20 @@ def hash_to_query_string(query_params) def self.hash_to_query_string(query_params) query_params.map do |k, v| - CGI.escape(k.to_s) + '=' + CGI.escape(v.to_s) + "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}" end.join('&') end def self.query_params_for_single_fetch(options) - Hash[options.select do |k, _v| + options.select do |k, _v| QUERY_PARAMS_FOR_SINGLE_FETCH.include? k - end] + end.to_h end def self.query_params_for_search(options) - Hash[options.select do |k, _v| + options.select do |k, _v| QUERY_PARAMS_FOR_SEARCH.include? k - end] + end.to_h end end end diff --git a/lib/jira/base_factory.rb b/lib/jira/base_factory.rb index 230b2d9a..02ec7087 100644 --- a/lib/jira/base_factory.rb +++ b/lib/jira/base_factory.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA # This is the base class for all the JIRA resource factory instances. class BaseFactory @@ -36,7 +38,8 @@ def self.delegate_to_target_class(*method_names) # The principle purpose of this class is to delegate methods to the corresponding # non-factory class and automatically prepend the client argument to the argument # list. - delegate_to_target_class :all, :find, :collection_path, :singular_path, :jql, :get_backlog_issues, :get_board_issues, :get_sprints, :get_sprint_issues, :get_projects, :get_projects_full + delegate_to_target_class :all, :find, :collection_path, :singular_path, :jql, :get_backlog_issues, + :get_board_issues, :get_sprints, :get_sprint_issues, :get_projects, :get_projects_full # This method needs special handling as it has a default argument value def build(attrs = {}) diff --git a/lib/jira/client.rb b/lib/jira/client.rb index d80fa754..a4a206ca 100644 --- a/lib/jira/client.rb +++ b/lib/jira/client.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'json' require 'forwardable' require 'ostruct' @@ -58,44 +60,45 @@ class Client # The configuration options for this client instance attr_reader :options - def_delegators :@request_client, :init_access_token, :set_access_token, :set_request_token, :request_token, :access_token, :authenticated? - - DEFINED_OPTIONS = [ - :site, - :context_path, - :signature_method, - :request_token_path, - :authorize_path, - :access_token_path, - :private_key, - :private_key_file, - :rest_base_path, - :consumer_key, - :consumer_secret, - :ssl_verify_mode, - :ssl_version, - :use_ssl, - :username, - :password, - :auth_type, - :proxy_address, - :proxy_port, - :proxy_username, - :proxy_password, - :use_cookies, - :additional_cookies, - :default_headers, - :use_client_cert, - :read_timeout, - :max_retries, - :http_debug, - :issuer, - :base_url, - :shared_secret, - :cert_path, - :key_path, - :ssl_client_cert, - :ssl_client_key + def_delegators :@request_client, :init_access_token, :set_access_token, :set_request_token, :request_token, + :access_token, :authenticated? + + DEFINED_OPTIONS = %i[ + site + context_path + signature_method + request_token_path + authorize_path + access_token_path + private_key + private_key_file + rest_base_path + consumer_key + consumer_secret + ssl_verify_mode + ssl_version + use_ssl + username + password + auth_type + proxy_address + proxy_port + proxy_username + proxy_password + use_cookies + additional_cookies + default_headers + use_client_cert + read_timeout + max_retries + http_debug + issuer + base_url + shared_secret + cert_path + key_path + ssl_client_cert + ssl_client_key ].freeze DEFAULT_OPTIONS = { @@ -119,11 +122,20 @@ def initialize(options = {}) raise ArgumentError, "Unknown option(s) given: #{unknown_options}" unless unknown_options.empty? if options[:use_client_cert] - @options[:ssl_client_cert] = OpenSSL::X509::Certificate.new(File.read(@options[:cert_path])) if @options[:cert_path] + if @options[:cert_path] + @options[:ssl_client_cert] = + OpenSSL::X509::Certificate.new(File.read(@options[:cert_path])) + end @options[:ssl_client_key] = OpenSSL::PKey::RSA.new(File.read(@options[:key_path])) if @options[:key_path] - raise ArgumentError, 'Options: :cert_path or :ssl_client_cert must be set when :use_client_cert is true' unless @options[:ssl_client_cert] - raise ArgumentError, 'Options: :key_path or :ssl_client_key must be set when :use_client_cert is true' unless @options[:ssl_client_key] + unless @options[:ssl_client_cert] + raise ArgumentError, + 'Options: :cert_path or :ssl_client_cert must be set when :use_client_cert is true' + end + unless @options[:ssl_client_key] + raise ArgumentError, + 'Options: :key_path or :ssl_client_key must be set when :use_client_cert is true' + end end case options[:auth_type] @@ -135,7 +147,11 @@ def initialize(options = {}) when :basic @request_client = HttpClient.new(@options) when :cookie - raise ArgumentError, 'Options: :use_cookies must be true for :cookie authorization type' if @options.key?(:use_cookies) && !@options[:use_cookies] + if @options.key?(:use_cookies) && !@options[:use_cookies] + raise ArgumentError, + 'Options: :use_cookies must be true for :cookie authorization type' + end + @options[:use_cookies] = true @request_client = HttpClient.new(@options) @request_client.make_cookie_auth_request diff --git a/lib/jira/has_many_proxy.rb b/lib/jira/has_many_proxy.rb index c32c392e..6e4764f9 100644 --- a/lib/jira/has_many_proxy.rb +++ b/lib/jira/has_many_proxy.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # # Whenever a collection from a has_many relationship is accessed, an instance # of this class is returned. This instance wraps the Array of instances in @@ -36,7 +38,7 @@ def all end # Delegate any missing methods to the collection that this proxy wraps - def method_missing(method_name, *args, &block) - collection.send(method_name, *args, &block) + def method_missing(method_name, ...) + collection.send(method_name, ...) end end diff --git a/lib/jira/http_client.rb b/lib/jira/http_client.rb index 6a659322..c395303c 100644 --- a/lib/jira/http_client.rb +++ b/lib/jira/http_client.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'json' require 'net/https' require 'cgi/cookie' @@ -21,7 +23,7 @@ def make_cookie_auth_request body = { username: @options[:username].to_s, password: @options[:password].to_s }.to_json @options.delete(:username) @options.delete(:password) - make_request(:post, @options[:context_path] + '/rest/auth/1/session', body, 'Content-Type' => 'application/json') + make_request(:post, "#{@options[:context_path]}/rest/auth/1/session", body, 'Content-Type' => 'application/json') end def make_request(http_method, url, body = '', headers = {}) @@ -47,7 +49,8 @@ def basic_auth_http_conn def http_conn(uri) http_conn = if @options[:proxy_address] - Net::HTTP.new(uri.host, uri.port, @options[:proxy_address], @options[:proxy_port] || 80, @options[:proxy_username], @options[:proxy_password]) + Net::HTTP.new(uri.host, uri.port, @options[:proxy_address], @options[:proxy_port] || 80, + @options[:proxy_username], @options[:proxy_password]) else Net::HTTP.new(uri.host, uri.port) end @@ -95,13 +98,13 @@ def request_path(url) def store_cookies(response) cookies = response.get_fields('set-cookie') - if cookies - cookies.each do |cookie| - data = CGI::Cookie.parse(cookie) - data.delete('Path') - @cookies.merge!(data) - end + return unless cookies + cookies.each do |cookie| + data = CGI::Cookie.parse(cookie) + data.delete('Path') + @cookies.merge!(data) end + end def add_cookies(request) diff --git a/lib/jira/http_error.rb b/lib/jira/http_error.rb index 9733531f..874e9867 100644 --- a/lib/jira/http_error.rb +++ b/lib/jira/http_error.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'forwardable' require 'active_support/core_ext/object' diff --git a/lib/jira/jwt_client.rb b/lib/jira/jwt_client.rb index 843d810a..1fa441ef 100644 --- a/lib/jira/jwt_client.rb +++ b/lib/jira/jwt_client.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'atlassian/jwt' module JIRA @@ -22,8 +24,8 @@ def make_multipart_request(url, data, headers = {}) def build_jwt_header(url) jwt = build_jwt(url) - - {'Authorization' => "JWT #{jwt}"} + + { 'Authorization' => "JWT #{jwt}" } end def build_jwt(url) @@ -38,4 +40,4 @@ def build_jwt(url) JWT.encode claim, @options[:shared_secret] end end -end \ No newline at end of file +end diff --git a/lib/jira/oauth_client.rb b/lib/jira/oauth_client.rb index bcbed350..4a1c47c5 100644 --- a/lib/jira/oauth_client.rb +++ b/lib/jira/oauth_client.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'oauth' require 'json' require 'forwardable' @@ -45,8 +47,8 @@ def init_oauth_consumer(_options) # Returns the current request token if it is set, else it creates # and sets a new token. - def request_token(options = {}, *arguments, &block) - @request_token ||= get_request_token(options, *arguments, &block) + def request_token(options = {}, ...) + @request_token ||= get_request_token(options, ...) end # Sets the request token from a given token and secret. @@ -71,6 +73,7 @@ def set_access_token(token, secret) # JIRA::Client::UninitializedAccessTokenError exception if it is not set. def access_token raise UninitializedAccessTokenError unless @access_token + @access_token end @@ -82,7 +85,7 @@ def make_request(http_method, url, body = '', headers = {}) uri.query = if uri.query.to_s == '' oauth_params_str else - uri.query + '&' + oauth_params_str + "#{uri.query}&#{oauth_params_str}" end url = uri.to_s end diff --git a/lib/jira/railtie.rb b/lib/jira/railtie.rb index 84809adb..0ba37b88 100644 --- a/lib/jira/railtie.rb +++ b/lib/jira/railtie.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'jira-ruby' require 'rails' diff --git a/lib/jira/request_client.rb b/lib/jira/request_client.rb index d90ae9d6..5a7d37d4 100644 --- a/lib/jira/request_client.rb +++ b/lib/jira/request_client.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'oauth' require 'json' require 'net/https' @@ -11,12 +13,14 @@ class RequestClient def request(*args) response = make_request(*args) raise HTTPError, response unless response.is_a?(Net::HTTPSuccess) + response end def request_multipart(*args) response = make_multipart_request(*args) raise HTTPError, response unless response.is_a?(Net::HTTPSuccess) + response end @@ -28,4 +32,4 @@ def make_multipart_request(*args) raise NotImplementedError end end -end \ No newline at end of file +end diff --git a/lib/jira/resource/agile.rb b/lib/jira/resource/agile.rb index 5f8f93e8..7ec278bc 100644 --- a/lib/jira/resource/agile.rb +++ b/lib/jira/resource/agile.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'cgi' module JIRA @@ -25,7 +27,8 @@ def self.get_board_issues(client, board_id, options = {}) response = client.get(path_base(client) + "/board/#{board_id}/issue?#{hash_to_query_string(options)}") json = parse_json(response.body) # To get Issue objects with the same structure as for Issue.all - return {} if json['issues'].size.zero? + return {} if json['issues'].empty? + issue_ids = json['issues'].map do |issue| issue['id'] end @@ -58,22 +61,17 @@ def self.get_projects(client, board_id, options = {}) parse_json(response.body) end - # def self.find(client, key, options = {}) - # options[:maxResults] ||= 100 - # fields = options[:fields].join(',') unless options[:fields].nil? - # response = client.get("/rest/api/latest/search?jql=sprint=#{key}&fields=#{fields}&maxResults=#{options[:maxResults]}") - # parse_json(response.body) - # end - private def self.path_base(client) - client.options[:context_path] + '/rest/agile/1.0' + "#{client.options[:context_path]}/rest/agile/1.0" end def path_base(client) self.class.path_base(client) end + + private_class_method :path_base end end end diff --git a/lib/jira/resource/applinks.rb b/lib/jira/resource/applinks.rb index 55f15ee2..80330341 100644 --- a/lib/jira/resource/applinks.rb +++ b/lib/jira/resource/applinks.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class ApplicationLinkFactory < JIRA::BaseFactory # :nodoc: @@ -5,7 +7,7 @@ class ApplicationLinkFactory < JIRA::BaseFactory # :nodoc: end class ApplicationLink < JIRA::Base - REST_BASE_PATH = '/rest/applinks/1.0'.freeze + REST_BASE_PATH = '/rest/applinks/1.0' def self.endpoint_name 'listApplicationlinks' @@ -24,12 +26,12 @@ def self.all(client, options = {}) json = parse_json(response.body) json = json['list'] json.map do |attrs| - new(client, { attrs: attrs }.merge(options)) + new(client, { attrs: }.merge(options)) end end def self.manifest(client) - url = full_url(client) + '/manifest' + url = "#{full_url(client)}/manifest" response = client.get(url) json = parse_json(response.body) JIRA::Base.new(client, attrs: json) diff --git a/lib/jira/resource/attachment.rb b/lib/jira/resource/attachment.rb index a0d6b8b1..a65001ed 100644 --- a/lib/jira/resource/attachment.rb +++ b/lib/jira/resource/attachment.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'net/http/post/multipart' require 'open-uri' @@ -64,7 +66,7 @@ def save!(attrs, path = url) headers = { 'X-Atlassian-Token' => 'nocheck' } data = { 'file' => Multipart::Post::UploadIO.new(file, mime_type, file) } - response = client.post_multipart(path, data , headers) + response = client.post_multipart(path, data, headers) set_attributes(attrs, response) diff --git a/lib/jira/resource/board.rb b/lib/jira/resource/board.rb index d78ec68a..88a7df99 100644 --- a/lib/jira/resource/board.rb +++ b/lib/jira/resource/board.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'cgi' module JIRA @@ -7,7 +9,7 @@ class BoardFactory < JIRA::BaseFactory # :nodoc: class Board < JIRA::Base def self.all(client) - path = path_base(client) + '/board' + path = "#{path_base(client)}/board" response = client.get(path) json = parse_json(response.body) results = json['values'] @@ -74,13 +76,13 @@ def project end def add_issue_to_backlog(issue) - client.post(path_base(client) + '/backlog/issue', { issues: [issue.id] }.to_json) + client.post("#{path_base(client)}/backlog/issue", { issues: [issue.id] }.to_json) end private def self.path_base(client) - client.options[:context_path] + '/rest/agile/1.0' + "#{client.options[:context_path]}/rest/agile/1.0" end def path_base(client) diff --git a/lib/jira/resource/board_configuration.rb b/lib/jira/resource/board_configuration.rb index fa152f8b..a8d15628 100644 --- a/lib/jira/resource/board_configuration.rb +++ b/lib/jira/resource/board_configuration.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class BoardConfigurationFactory < JIRA::BaseFactory # :nodoc: diff --git a/lib/jira/resource/comment.rb b/lib/jira/resource/comment.rb index 8b521149..d1475f67 100644 --- a/lib/jira/resource/comment.rb +++ b/lib/jira/resource/comment.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class CommentFactory < JIRA::BaseFactory # :nodoc: diff --git a/lib/jira/resource/component.rb b/lib/jira/resource/component.rb index 52ef8bea..881e4091 100644 --- a/lib/jira/resource/component.rb +++ b/lib/jira/resource/component.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class ComponentFactory < JIRA::BaseFactory # :nodoc: diff --git a/lib/jira/resource/createmeta.rb b/lib/jira/resource/createmeta.rb index e77c972b..6f53b0c6 100644 --- a/lib/jira/resource/createmeta.rb +++ b/lib/jira/resource/createmeta.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class CreatemetaFactory < JIRA::BaseFactory # :nodoc: @@ -36,7 +38,7 @@ def self.all(client, params = {}) json = parse_json(response.body) json['projects'].map do |attrs| - new(client, attrs: attrs) + new(client, attrs:) end end end diff --git a/lib/jira/resource/field.rb b/lib/jira/resource/field.rb index 5879002c..227e474c 100644 --- a/lib/jira/resource/field.rb +++ b/lib/jira/resource/field.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class FieldFactory < JIRA::BaseFactory # :nodoc: @@ -26,20 +28,22 @@ def self.map_fields(client) # as a system field can't take precedence fields.each do |f| next if f.custom + name = safe_name(f.name) field_map_reverse[f.id] = [f.name, name] # capture both the official name, and the mapped name field_map[name] = f.id end - fields.each do |f| + fields.each do |f| # rubocop:disable Style/CombinableLoops next unless f.custom + name = if field_map.key? f.name renamed = safer_name(f.name, f.id) warn "Duplicate Field name #{f.name} #{f.id} - renaming as #{renamed}" renamed else safe_name(f.name) - end + end field_map_reverse[f.id] = [f.name, name] # capture both the official name, and the mapped name field_map[name] = f.id end @@ -55,6 +59,7 @@ def self.field_map(client) def self.name_to_id(client, field_name) field_name = field_name.to_s return field_name unless client.cache.field_map && client.cache.field_map[field_name] + client.cache.field_map[field_name] end @@ -66,7 +71,7 @@ def respond_to?(method_name, _include_all = false) end end - def method_missing(method_name, *args, &block) + def method_missing(method_name, *args, &) if attrs.key?(method_name.to_s) attrs[method_name.to_s] else @@ -74,7 +79,7 @@ def method_missing(method_name, *args, &block) if attrs.key?(official_name) attrs[official_name] else - super(method_name, *args, &block) + super(method_name, *args, &) end end end diff --git a/lib/jira/resource/filter.rb b/lib/jira/resource/filter.rb index 8a42d319..d32eac98 100644 --- a/lib/jira/resource/filter.rb +++ b/lib/jira/resource/filter.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class FilterFactory < JIRA::BaseFactory # :nodoc: diff --git a/lib/jira/resource/issue.rb b/lib/jira/resource/issue.rb index 2d9e75b8..bda42eb5 100644 --- a/lib/jira/resource/issue.rb +++ b/lib/jira/resource/issue.rb @@ -1,53 +1,33 @@ +# frozen_string_literal: true + require 'cgi' require 'json' - module JIRA module Resource class IssueFactory < JIRA::BaseFactory # :nodoc: end class Issue < JIRA::Base - has_one :reporter, class: JIRA::Resource::User, - nested_under: 'fields' - has_one :assignee, class: JIRA::Resource::User, - nested_under: 'fields' - has_one :project, nested_under: 'fields' - + has_one :reporter, class: JIRA::Resource::User, nested_under: 'fields' + has_one :assignee, class: JIRA::Resource::User, nested_under: 'fields' + has_one :project, nested_under: 'fields' has_one :issuetype, nested_under: 'fields' - - has_one :priority, nested_under: 'fields' - - has_one :status, nested_under: 'fields' - + has_one :priority, nested_under: 'fields' + has_one :status, nested_under: 'fields' has_one :resolution, nested_under: 'fields' - has_many :transitions - has_many :components, nested_under: 'fields' - has_many :comments, nested_under: %w[fields comment] - - has_many :attachments, nested_under: 'fields', - attribute_key: 'attachment' - - has_many :versions, nested_under: 'fields' - has_many :fixVersions, class: JIRA::Resource::Version, - nested_under: 'fields' - + has_many :attachments, nested_under: 'fields', attribute_key: 'attachment' + has_many :versions, nested_under: 'fields' + has_many :fixVersions, class: JIRA::Resource::Version, nested_under: 'fields' has_many :worklogs, nested_under: %w[fields worklog] - has_one :sprint, class: JIRA::Resource::Sprint, - nested_under: 'fields' - - has_many :closed_sprints, class: JIRA::Resource::Sprint, - nested_under: 'fields', attribute_key: 'closedSprints' - + has_one :sprint, class: JIRA::Resource::Sprint, nested_under: 'fields' + has_many :closed_sprints, class: JIRA::Resource::Sprint, nested_under: 'fields', attribute_key: 'closedSprints' has_many :issuelinks, nested_under: 'fields' - has_many :remotelink, class: JIRA::Resource::Remotelink - - has_many :watchers, attribute_key: 'watches', - nested_under: %w[fields watches] + has_many :watchers, attribute_key: 'watches', nested_under: %w[fields watches] def self.all(client) start_at = 0 @@ -62,15 +42,21 @@ def self.all(client) result.push(client.Issue.build(issue)) end break if json['issues'].empty? + start_at += json['issues'].size end result end - def self.jql(client, jql, options = { fields: nil, start_at: nil, max_results: nil, expand: nil, validate_query: true }) + def self.jql(client, jql, options = { fields: nil, start_at: nil, max_results: nil, expand: nil, +validate_query: true }) url = client.options[:rest_base_path] + "/search?jql=#{CGI.escape(jql)}" - url << "&fields=#{options[:fields].map { |value| CGI.escape(client.Field.name_to_id(value)) }.join(',')}" if options[:fields] + if options[:fields] + url << "&fields=#{options[:fields].map do |value| + CGI.escape(client.Field.name_to_id(value)) + end.join(',')}" + end url << "&startAt=#{CGI.escape(options[:start_at].to_s)}" if options[:start_at] url << "&maxResults=#{CGI.escape(options[:max_results].to_s)}" if options[:max_results] url << '&validateQuery=false' if options[:validate_query] === false @@ -82,9 +68,8 @@ def self.jql(client, jql, options = { fields: nil, start_at: nil, max_results: n response = client.get(url) json = parse_json(response.body) - if options[:max_results] && (options[:max_results] == 0) - return json['total'] - end + return json['total'] if options[:max_results] && (options[:max_results]).zero? + json['issues'].map do |issue| client.Issue.build(issue) end @@ -95,14 +80,15 @@ def self.jql(client, jql, options = { fields: nil, start_at: nil, max_results: n # is not set def fetch(reload = false, query_params = {}) return if expanded? && !reload + response = client.get(url_with_query_params(url, query_params)) set_attrs_from_response(response) - if @attrs && @attrs['fields'] && @attrs['fields']['worklog'] && (@attrs['fields']['worklog']['total'] > @attrs['fields']['worklog']['maxResults']) + if @attrs && @attrs['fields'] && + @attrs['fields']['worklog'] && + (@attrs['fields']['worklog']['total'] > @attrs['fields']['worklog']['maxResults']) worklog_url = client.options[:rest_base_path] + "/#{self.class.endpoint_name}/#{id}/worklog" response = client.get(worklog_url) - unless response.body.nil? || (response.body.length < 2) - set_attrs({ 'fields' => { 'worklog' => self.class.parse_json(response.body) } }, false) - end + set_attrs({ 'fields' => { 'worklog' => self.class.parse_json(response.body) } }, false) unless response.body.nil? || (response.body.length < 2) end @expanded = true end @@ -116,14 +102,16 @@ def editmeta end def respond_to?(method_name, _include_all = false) - if attrs.key?('fields') && [method_name.to_s, client.Field.name_to_id(method_name)].any? { |k| attrs['fields'].key?(k) } + if attrs.key?('fields') && [method_name.to_s, client.Field.name_to_id(method_name)].any? do |k| + attrs['fields'].key?(k) + end true else super(method_name) end end - def method_missing(method_name, *args, &block) + def method_missing(method_name, *args, &) if attrs.key?('fields') if attrs['fields'].key?(method_name.to_s) attrs['fields'][method_name.to_s] @@ -132,11 +120,11 @@ def method_missing(method_name, *args, &block) if attrs['fields'].key?(official_name) attrs['fields'][official_name] else - super(method_name, *args, &block) + super(method_name, *args, &) end end else - super(method_name, *args, &block) + super(method_name, *args, &) end end end diff --git a/lib/jira/resource/issue_picker_suggestions.rb b/lib/jira/resource/issue_picker_suggestions.rb index 2834c16a..6408749a 100644 --- a/lib/jira/resource/issue_picker_suggestions.rb +++ b/lib/jira/resource/issue_picker_suggestions.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class IssuePickerSuggestionsFactory < JIRA::BaseFactory # :nodoc: @@ -6,7 +8,8 @@ class IssuePickerSuggestionsFactory < JIRA::BaseFactory # :nodoc: class IssuePickerSuggestions < JIRA::Base has_many :sections, class: JIRA::Resource::IssuePickerSuggestionsIssue - def self.all(client, query = '', options = { current_jql: nil, current_issue_key: nil, current_project_id: nil, show_sub_tasks: nil, show_sub_tasks_parent: nil }) + def self.all(client, query = '', options = { current_jql: nil, current_issue_key: nil, current_project_id: nil, +show_sub_tasks: nil, show_sub_tasks_parent: nil }) url = client.options[:rest_base_path] + "/issue/picker?query=#{CGI.escape(query)}" url << "¤tJQL=#{CGI.escape(options[:current_jql])}" if options[:current_jql] diff --git a/lib/jira/resource/issue_picker_suggestions_issue.rb b/lib/jira/resource/issue_picker_suggestions_issue.rb index 4d54c90b..2756e2d4 100644 --- a/lib/jira/resource/issue_picker_suggestions_issue.rb +++ b/lib/jira/resource/issue_picker_suggestions_issue.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class IssuePickerSuggestionsIssueFactory < JIRA::BaseFactory # :nodoc: diff --git a/lib/jira/resource/issuelink.rb b/lib/jira/resource/issuelink.rb index a960bd67..cf3e5e29 100644 --- a/lib/jira/resource/issuelink.rb +++ b/lib/jira/resource/issuelink.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class IssuelinkFactory < JIRA::BaseFactory # :nodoc: diff --git a/lib/jira/resource/issuelinktype.rb b/lib/jira/resource/issuelinktype.rb index 29010c67..4cf1e4c2 100644 --- a/lib/jira/resource/issuelinktype.rb +++ b/lib/jira/resource/issuelinktype.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class IssuelinktypeFactory < JIRA::BaseFactory # :nodoc: diff --git a/lib/jira/resource/issuetype.rb b/lib/jira/resource/issuetype.rb index 9f47d7e1..20d762de 100644 --- a/lib/jira/resource/issuetype.rb +++ b/lib/jira/resource/issuetype.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class IssuetypeFactory < JIRA::BaseFactory # :nodoc: diff --git a/lib/jira/resource/priority.rb b/lib/jira/resource/priority.rb index 385443b4..296e4313 100644 --- a/lib/jira/resource/priority.rb +++ b/lib/jira/resource/priority.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class PriorityFactory < JIRA::BaseFactory # :nodoc: diff --git a/lib/jira/resource/project.rb b/lib/jira/resource/project.rb index 5db9403d..b51c1912 100644 --- a/lib/jira/resource/project.rb +++ b/lib/jira/resource/project.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class ProjectFactory < JIRA::BaseFactory # :nodoc: @@ -15,7 +17,7 @@ def self.key_attribute # Returns all the issues for this project def issues(options = {}) - search_url = client.options[:rest_base_path] + '/search' + search_url = "#{client.options[:rest_base_path]}/search" query_params = { jql: "project=\"#{key}\"" } query_params.update Base.query_params_for_search(options) response = client.get(url_with_query_params(search_url, query_params)) @@ -26,7 +28,7 @@ def issues(options = {}) end def users(start_at: nil, max_results: nil) - users_url = client.options[:rest_base_path] + '/user/assignable/search' + users_url = "#{client.options[:rest_base_path]}/user/assignable/search" query_params = { project: key_value } query_params['startAt'] = start_at if start_at query_params['maxResults'] = max_results if max_results diff --git a/lib/jira/resource/rapidview.rb b/lib/jira/resource/rapidview.rb index 9b96285c..fede5c2d 100644 --- a/lib/jira/resource/rapidview.rb +++ b/lib/jira/resource/rapidview.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'cgi' module JIRA @@ -7,7 +9,7 @@ class RapidViewFactory < JIRA::BaseFactory # :nodoc: class RapidView < JIRA::Base def self.all(client) - response = client.get(path_base(client) + '/rapidview') + response = client.get("#{path_base(client)}/rapidview") json = parse_json(response.body) json['views'].map do |view| client.RapidView.build(view) @@ -44,7 +46,7 @@ def issues(options = {}) def sprints(options = {}) params = { includeHistoricSprints: options.fetch(:include_historic, false), - includeFutureSprints: options.fetch(:include_future, false) } + includeFutureSprints: options.fetch(:include_future, false) } response = client.get(path_base(client) + "/sprintquery/#{id}?#{params.to_query}") json = self.class.parse_json(response.body) json['sprints'].map do |sprint| @@ -56,7 +58,7 @@ def sprints(options = {}) private def self.path_base(client) - client.options[:context_path] + '/rest/greenhopper/1.0' + "#{client.options[:context_path]}/rest/greenhopper/1.0" end def path_base(client) diff --git a/lib/jira/resource/remotelink.rb b/lib/jira/resource/remotelink.rb index 63c6a9e6..6d8fe86d 100644 --- a/lib/jira/resource/remotelink.rb +++ b/lib/jira/resource/remotelink.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class RemotelinkFactory < JIRA::BaseFactory # :nodoc: diff --git a/lib/jira/resource/resolution.rb b/lib/jira/resource/resolution.rb index a3a6359c..557e87f3 100644 --- a/lib/jira/resource/resolution.rb +++ b/lib/jira/resource/resolution.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class ResolutionFactory < JIRA::BaseFactory # :nodoc: diff --git a/lib/jira/resource/serverinfo.rb b/lib/jira/resource/serverinfo.rb index 8a290871..ad29eff0 100644 --- a/lib/jira/resource/serverinfo.rb +++ b/lib/jira/resource/serverinfo.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class ServerInfoFactory < JIRA::BaseFactory # :nodoc: diff --git a/lib/jira/resource/sprint.rb b/lib/jira/resource/sprint.rb index 5664c44c..61219035 100644 --- a/lib/jira/resource/sprint.rb +++ b/lib/jira/resource/sprint.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class SprintFactory < JIRA::BaseFactory # :nodoc: @@ -12,7 +14,7 @@ def self.find(client, key) # get all issues of sprint def issues(options = {}) - jql = "sprint = #{id.to_s}" + jql = "sprint = #{id}" jql += " and updated >= '#{options[:updated]}'" if options[:updated] Issue.jql(client, jql) end diff --git a/lib/jira/resource/status.rb b/lib/jira/resource/status.rb index be53507f..10d18d8a 100644 --- a/lib/jira/resource/status.rb +++ b/lib/jira/resource/status.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative 'status_category' module JIRA diff --git a/lib/jira/resource/status_category.rb b/lib/jira/resource/status_category.rb index c900308c..e82c7f52 100644 --- a/lib/jira/resource/status_category.rb +++ b/lib/jira/resource/status_category.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class StatusCategoryFactory < JIRA::BaseFactory # :nodoc: diff --git a/lib/jira/resource/suggested_issue.rb b/lib/jira/resource/suggested_issue.rb index 7fe7d00d..75d4ed22 100644 --- a/lib/jira/resource/suggested_issue.rb +++ b/lib/jira/resource/suggested_issue.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class SuggestedIssueFactory < JIRA::BaseFactory # :nodoc: diff --git a/lib/jira/resource/transition.rb b/lib/jira/resource/transition.rb index e865c6f6..c1d4a8fe 100644 --- a/lib/jira/resource/transition.rb +++ b/lib/jira/resource/transition.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class TransitionFactory < JIRA::BaseFactory # :nodoc: diff --git a/lib/jira/resource/user.rb b/lib/jira/resource/user.rb index 7cb64b41..f4a4b57b 100644 --- a/lib/jira/resource/user.rb +++ b/lib/jira/resource/user.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class UserFactory < JIRA::BaseFactory # :nodoc: @@ -13,7 +15,7 @@ class User < JIRA::Base MAX_RESULTS = 1000 def self.singular_path(client, key, prefix = '/') - collection_path(client, prefix) + '?accountId=' + key + "#{collection_path(client, prefix)}?accountId=#{key}" end # Cannot retrieve more than 1,000 users through the api, please see: https://jira.atlassian.com/browse/JRASERVER-65089 diff --git a/lib/jira/resource/version.rb b/lib/jira/resource/version.rb index 1861a951..e59cacdb 100644 --- a/lib/jira/resource/version.rb +++ b/lib/jira/resource/version.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class VersionFactory < JIRA::BaseFactory # :nodoc: diff --git a/lib/jira/resource/watcher.rb b/lib/jira/resource/watcher.rb index be9f16da..3259a359 100644 --- a/lib/jira/resource/watcher.rb +++ b/lib/jira/resource/watcher.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class WatcherFactory < JIRA::BaseFactory # :nodoc: @@ -29,7 +31,6 @@ def save!(user_id, path = nil) response = client.post(path, user_id.to_json) true end - end end end diff --git a/lib/jira/resource/webhook.rb b/lib/jira/resource/webhook.rb index f35805a6..6c6c2fd0 100644 --- a/lib/jira/resource/webhook.rb +++ b/lib/jira/resource/webhook.rb @@ -1,10 +1,12 @@ +# frozen_string_literal: true + module JIRA module Resource class WebhookFactory < JIRA::BaseFactory # :nodoc: end class Webhook < JIRA::Base - REST_BASE_PATH = '/rest/webhooks/1.0'.freeze + REST_BASE_PATH = '/rest/webhooks/1.0' def self.endpoint_name 'webhook' @@ -22,7 +24,7 @@ def self.all(client, options = {}) response = client.get(collection_path(client)) json = parse_json(response.body) json.map do |attrs| - new(client, { attrs: attrs }.merge(options)) + new(client, { attrs: }.merge(options)) end end diff --git a/lib/jira/resource/worklog.rb b/lib/jira/resource/worklog.rb index c57886ab..325d8534 100644 --- a/lib/jira/resource/worklog.rb +++ b/lib/jira/resource/worklog.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA module Resource class WorklogFactory < JIRA::BaseFactory # :nodoc: @@ -5,8 +7,7 @@ class WorklogFactory < JIRA::BaseFactory # :nodoc: class Worklog < JIRA::Base has_one :author, class: JIRA::Resource::User - has_one :update_author, class: JIRA::Resource::User, - attribute_key: 'updateAuthor' + has_one :update_author, class: JIRA::Resource::User, attribute_key: 'updateAuthor' belongs_to :issue nested_collections true end diff --git a/lib/jira/tasks.rb b/lib/jira/tasks.rb deleted file mode 100644 index e69de29b..00000000 diff --git a/lib/jira/version.rb b/lib/jira/version.rb index afd85d02..dad2941f 100644 --- a/lib/jira/version.rb +++ b/lib/jira/version.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JIRA - VERSION = '3.0.0'.freeze + VERSION = '3.0.0' end diff --git a/lib/tasks/generate.rake b/lib/tasks/generate.rake index 51690670..3880cc47 100644 --- a/lib/tasks/generate.rake +++ b/lib/tasks/generate.rake @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'securerandom' namespace :jira do @@ -10,8 +12,8 @@ namespace :jira do desc 'Run the system call to generate a RSA public certificate' task :generate_public_cert do puts "Executing 'openssl req -x509 -nodes -newkey rsa:1024 -sha1 -keyout rsakey.pem -out rsacert.pem'" - 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') - puts "Done. The RSA-SHA1 private keyfile is in the current directory: \'rsakey.pem\'." + 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') # rubocop:disable Layout/LineLength + puts "Done. The RSA-SHA1 private keyfile is in the current directory: 'rsakey.pem'." puts 'You will need to copy the following certificate into your application link configuration in Jira:' system('cat rsacert.pem') end diff --git a/spec/integration/attachment_spec.rb b/spec/integration/attachment_spec.rb index 1a945608..0804318f 100644 --- a/spec/integration/attachment_spec.rb +++ b/spec/integration/attachment_spec.rb @@ -7,7 +7,7 @@ let(:key) { '10000' } - let(:target) { JIRA::Resource::Attachment.new(client, attrs: { 'id' => '99999' }, issue_id: '10002') } + let(:target) { described_class.new(client, attrs: { 'id' => '99999' }, issue_id: '10002') } let(:expected_attributes) do { @@ -26,7 +26,7 @@ }) end - it_should_behave_like 'a resource with a singular GET endpoint' - it_should_behave_like 'a resource with a DELETE endpoint' + it_behaves_like 'a resource with a singular GET endpoint' + it_behaves_like 'a resource with a DELETE endpoint' end end diff --git a/spec/integration/comment_spec.rb b/spec/integration/comment_spec.rb index a8157467..b644efa3 100644 --- a/spec/integration/comment_spec.rb +++ b/spec/integration/comment_spec.rb @@ -7,7 +7,7 @@ let(:key) { '10000' } - let(:target) { JIRA::Resource::Comment.new(client, attrs: { 'id' => '99999' }, issue_id: '54321') } + let(:target) { described_class.new(client, attrs: { 'id' => '99999' }, issue_id: '54321') } let(:expected_collection_length) { 2 } @@ -23,7 +23,7 @@ let(:expected_attributes) do { 'self' => 'http://localhost:2990/jira/rest/api/2/issue/10002/comment/10000', - 'id' => key, + 'id' => key, 'body' => 'This is a comment. Creative.' } end @@ -42,11 +42,11 @@ { 'id' => '10000', 'body' => 'new body' } end - it_should_behave_like 'a resource' - it_should_behave_like 'a resource with a collection GET endpoint' - it_should_behave_like 'a resource with a singular GET endpoint' - it_should_behave_like 'a resource with a DELETE endpoint' - it_should_behave_like 'a resource with a POST endpoint' - it_should_behave_like 'a resource with a PUT endpoint' + it_behaves_like 'a resource' + it_behaves_like 'a resource with a collection GET endpoint' + it_behaves_like 'a resource with a singular GET endpoint' + it_behaves_like 'a resource with a DELETE endpoint' + it_behaves_like 'a resource with a POST endpoint' + it_behaves_like 'a resource with a PUT endpoint' end end diff --git a/spec/integration/component_spec.rb b/spec/integration/component_spec.rb index 8e76bf58..ee5771f5 100644 --- a/spec/integration/component_spec.rb +++ b/spec/integration/component_spec.rb @@ -10,7 +10,7 @@ let(:expected_attributes) do { 'self' => 'http://localhost:2990/jira/rest/api/2/component/10000', - 'id' => key, + 'id' => key, 'name' => 'Cheesecake' } end @@ -29,11 +29,11 @@ { 'id' => '10000', 'name' => 'Jammy' } end - it_should_behave_like 'a resource' - it_should_behave_like 'a resource with a singular GET endpoint' - it_should_behave_like 'a resource with a DELETE endpoint' - it_should_behave_like 'a resource with a POST endpoint' - it_should_behave_like 'a resource with a PUT endpoint' - it_should_behave_like 'a resource with a PUT endpoint that rejects invalid fields' + it_behaves_like 'a resource' + it_behaves_like 'a resource with a singular GET endpoint' + it_behaves_like 'a resource with a DELETE endpoint' + it_behaves_like 'a resource with a POST endpoint' + it_behaves_like 'a resource with a PUT endpoint' + it_behaves_like 'a resource with a PUT endpoint that rejects invalid fields' end end diff --git a/spec/integration/field_spec.rb b/spec/integration/field_spec.rb index 6eca3549..e3912699 100644 --- a/spec/integration/field_spec.rb +++ b/spec/integration/field_spec.rb @@ -25,8 +25,8 @@ let(:expected_collection_length) { 2 } - it_should_behave_like 'a resource' - it_should_behave_like 'a resource with a collection GET endpoint' - it_should_behave_like 'a resource with a singular GET endpoint' + it_behaves_like 'a resource' + it_behaves_like 'a resource with a collection GET endpoint' + it_behaves_like 'a resource with a singular GET endpoint' end end diff --git a/spec/integration/issue_spec.rb b/spec/integration/issue_spec.rb index c1384376..8aa4b128 100644 --- a/spec/integration/issue_spec.rb +++ b/spec/integration/issue_spec.rb @@ -9,8 +9,8 @@ let(:expected_attributes) do { - 'self' => 'http://localhost:2990/jira/rest/api/2/issue/10002', - 'key' => 'SAMPLEPROJECT-1', + 'self' => 'http://localhost:2990/jira/rest/api/2/issue/10002', + 'key' => 'SAMPLEPROJECT-1', 'expand' => 'renderedFields,names,schema,transitions,editmeta,changelog' } end @@ -30,8 +30,8 @@ end let(:expected_collection_length) { 11 } - it_should_behave_like 'a resource' - it_should_behave_like 'a resource with a singular GET endpoint' + it_behaves_like 'a resource' + it_behaves_like 'a resource with a singular GET endpoint' describe 'GET all issues' do # JIRA::Resource::Issue.all uses the search endpoint let(:client) { client } let(:site_url) { site_url } @@ -43,26 +43,29 @@ 'key' => 'SAMPLEPROJECT-13' } end - before(:each) do - stub_request(:get, site_url + '/jira/rest/api/2/search?expand=transitions.fields&maxResults=1000&startAt=0') + + before do + stub_request(:get, "#{site_url}/jira/rest/api/2/search?expand=transitions.fields&maxResults=1000&startAt=0") .to_return(status: 200, body: get_mock_response('issue.json')) - stub_request(:get, site_url + '/jira/rest/api/2/search?expand=transitions.fields&maxResults=1000&startAt=11') + stub_request(:get, "#{site_url}/jira/rest/api/2/search?expand=transitions.fields&maxResults=1000&startAt=11") .to_return(status: 200, body: get_mock_response('empty_issues.json')) end - it_should_behave_like 'a resource with a collection GET endpoint' + + it_behaves_like 'a resource with a collection GET endpoint' end - it_should_behave_like 'a resource with a DELETE endpoint' - it_should_behave_like 'a resource with a POST endpoint' - it_should_behave_like 'a resource with a PUT endpoint' - it_should_behave_like 'a resource with a PUT endpoint that rejects invalid fields' + + it_behaves_like 'a resource with a DELETE endpoint' + it_behaves_like 'a resource with a POST endpoint' + it_behaves_like 'a resource with a PUT endpoint' + it_behaves_like 'a resource with a PUT endpoint that rejects invalid fields' describe 'errors' do - before(:each) do + before do stub_request(:get, - site_url + '/jira/rest/api/2/issue/10002') + "#{site_url}/jira/rest/api/2/issue/10002") .to_return(status: 200, body: get_mock_response('issue/10002.json')) - stub_request(:put, site_url + '/jira/rest/api/2/issue/10002') + stub_request(:put, "#{site_url}/jira/rest/api/2/issue/10002") .with(body: '{"missing":"fields and update"}') .to_return(status: 400, body: get_mock_response('issue/10002.put.missing_field_update.json')) end @@ -87,7 +90,8 @@ 'key' => 'SAMPLEPROJECT-13' } end - it_should_behave_like 'a resource with JQL inputs and a collection GET endpoint' + + it_behaves_like 'a resource with JQL inputs and a collection GET endpoint' end end end diff --git a/spec/integration/issuelinktype_spec.rb b/spec/integration/issuelinktype_spec.rb index ac9dbbd3..8b9dd3d9 100644 --- a/spec/integration/issuelinktype_spec.rb +++ b/spec/integration/issuelinktype_spec.rb @@ -19,8 +19,8 @@ let(:expected_collection_length) { 3 } - it_should_behave_like 'a resource' - it_should_behave_like 'a resource with a collection GET endpoint' - it_should_behave_like 'a resource with a singular GET endpoint' + it_behaves_like 'a resource' + it_behaves_like 'a resource with a collection GET endpoint' + it_behaves_like 'a resource with a singular GET endpoint' end end diff --git a/spec/integration/issuetype_spec.rb b/spec/integration/issuetype_spec.rb index 1618a58a..2433492c 100644 --- a/spec/integration/issuetype_spec.rb +++ b/spec/integration/issuetype_spec.rb @@ -17,8 +17,8 @@ let(:expected_collection_length) { 5 } - it_should_behave_like 'a resource' - it_should_behave_like 'a resource with a collection GET endpoint' - it_should_behave_like 'a resource with a singular GET endpoint' + it_behaves_like 'a resource' + it_behaves_like 'a resource with a collection GET endpoint' + it_behaves_like 'a resource with a singular GET endpoint' end end diff --git a/spec/integration/priority_spec.rb b/spec/integration/priority_spec.rb index d4194626..f4e6e335 100644 --- a/spec/integration/priority_spec.rb +++ b/spec/integration/priority_spec.rb @@ -17,8 +17,8 @@ let(:expected_collection_length) { 5 } - it_should_behave_like 'a resource' - it_should_behave_like 'a resource with a collection GET endpoint' - it_should_behave_like 'a resource with a singular GET endpoint' + it_behaves_like 'a resource' + it_behaves_like 'a resource with a collection GET endpoint' + it_behaves_like 'a resource with a singular GET endpoint' end end diff --git a/spec/integration/project_spec.rb b/spec/integration/project_spec.rb index 19a9b1ec..0903ebdc 100644 --- a/spec/integration/project_spec.rb +++ b/spec/integration/project_spec.rb @@ -9,21 +9,21 @@ let(:expected_attributes) do { - 'self' => 'http://localhost:2990/jira/rest/api/2/project/SAMPLEPROJECT', - 'key' => key, - 'name' => 'Sample Project for Developing RoR RESTful API' + 'self' => 'http://localhost:2990/jira/rest/api/2/project/SAMPLEPROJECT', + 'key' => key, + 'name' => 'Sample Project for Developing RoR RESTful API' } end let(:expected_collection_length) { 1 } - it_should_behave_like 'a resource' - it_should_behave_like 'a resource with a collection GET endpoint' - it_should_behave_like 'a resource with a singular GET endpoint' + it_behaves_like 'a resource' + it_behaves_like 'a resource with a collection GET endpoint' + it_behaves_like 'a resource with a singular GET endpoint' describe 'issues' do it 'returns all the issues' do - stub_request(:get, site_url + '/jira/rest/api/2/search?jql=project="SAMPLEPROJECT"') + stub_request(:get, "#{site_url}/jira/rest/api/2/search?jql=project=\"SAMPLEPROJECT\"") .to_return(status: 200, body: get_mock_response('project/SAMPLEPROJECT.issues.json')) subject = client.Project.build('key' => key) issues = subject.issues diff --git a/spec/integration/rapidview_spec.rb b/spec/integration/rapidview_spec.rb index 042cc7b3..b3ccfbc7 100644 --- a/spec/integration/rapidview_spec.rb +++ b/spec/integration/rapidview_spec.rb @@ -18,7 +18,7 @@ } end - it_should_behave_like 'a resource' + it_behaves_like 'a resource' # TODO@Anton: Add json file # it_should_behave_like 'a resource with a singular GET endpoint' @@ -26,19 +26,19 @@ let(:client) { client } let(:site_url) { site_url } - before(:each) do - stub_request(:get, site_url + '/jira/rest/greenhopper/1.0/rapidview') + before do + stub_request(:get, "#{site_url}/jira/rest/greenhopper/1.0/rapidview") .to_return(status: 200, body: get_mock_response('rapidview.json')) end - it_should_behave_like 'a resource with a collection GET endpoint' + + it_behaves_like 'a resource with a collection GET endpoint' end describe 'issues' do - it 'should return all the issues' do + it 'returns all the issues' do stub_request( :get, - site_url + - '/jira/rest/greenhopper/1.0/xboard/plan/backlog/data?rapidViewId=1' + "#{site_url}/jira/rest/greenhopper/1.0/xboard/plan/backlog/data?rapidViewId=1" ).to_return( status: 200, body: get_mock_response('rapidview/SAMPLEPROJECT.issues.json') @@ -46,7 +46,7 @@ stub_request( :get, - site_url + '/jira/rest/api/2/search?jql=id IN(10001, 10000)' + "#{site_url}/jira/rest/api/2/search?jql=id IN(10001, 10000)" ).to_return( status: 200, body: get_mock_response('rapidview/SAMPLEPROJECT.issues.full.json') @@ -54,7 +54,7 @@ stub_request( :get, - site_url + '/jira/rest/api/2/search?jql=id IN(10000, 10001) AND sprint IS NOT EMPTY' + "#{site_url}/jira/rest/api/2/search?jql=id IN(10000, 10001) AND sprint IS NOT EMPTY" ).to_return( status: 200, body: get_mock_response('rapidview/SAMPLEPROJECT.issues.full.json') diff --git a/spec/integration/resolution_spec.rb b/spec/integration/resolution_spec.rb index 725ef0b7..7b7f6293 100644 --- a/spec/integration/resolution_spec.rb +++ b/spec/integration/resolution_spec.rb @@ -19,8 +19,8 @@ let(:expected_collection_length) { 2 } - it_should_behave_like 'a resource' - it_should_behave_like 'a resource with a collection GET endpoint' - it_should_behave_like 'a resource with a singular GET endpoint' + it_behaves_like 'a resource' + it_behaves_like 'a resource with a collection GET endpoint' + it_behaves_like 'a resource with a singular GET endpoint' end end diff --git a/spec/integration/status_category_spec.rb b/spec/integration/status_category_spec.rb index 5453f807..f95fd733 100644 --- a/spec/integration/status_category_spec.rb +++ b/spec/integration/status_category_spec.rb @@ -13,8 +13,8 @@ let(:expected_collection_length) { 4 } - it_should_behave_like 'a resource' - it_should_behave_like 'a resource with a collection GET endpoint' - it_should_behave_like 'a resource with a singular GET endpoint' + it_behaves_like 'a resource' + it_behaves_like 'a resource with a collection GET endpoint' + it_behaves_like 'a resource with a singular GET endpoint' end end diff --git a/spec/integration/status_spec.rb b/spec/integration/status_spec.rb index 3a74e764..c3087f96 100644 --- a/spec/integration/status_spec.rb +++ b/spec/integration/status_spec.rb @@ -13,8 +13,8 @@ let(:expected_collection_length) { 5 } - it_should_behave_like 'a resource' - it_should_behave_like 'a resource with a collection GET endpoint' - it_should_behave_like 'a resource with a singular GET endpoint' + it_behaves_like 'a resource' + it_behaves_like 'a resource with a collection GET endpoint' + it_behaves_like 'a resource with a singular GET endpoint' end end diff --git a/spec/integration/transition_spec.rb b/spec/integration/transition_spec.rb index 6c6f0835..d8a6518b 100644 --- a/spec/integration/transition_spec.rb +++ b/spec/integration/transition_spec.rb @@ -7,7 +7,7 @@ let(:key) { '10000' } - let(:target) { JIRA::Resource::Transition.new(client, attrs: { 'id' => '99999' }, issue_id: '10014') } + let(:target) { described_class.new(client, attrs: { 'id' => '99999' }, issue_id: '10014') } let(:belongs_to) do JIRA::Resource::Issue.new(client, attrs: { @@ -34,7 +34,7 @@ } end - it_should_behave_like 'a resource' + it_behaves_like 'a resource' describe 'POST endpoint' do it 'saves a new resource' do diff --git a/spec/integration/user_spec.rb b/spec/integration/user_spec.rb index b7275f4c..5f9a716a 100644 --- a/spec/integration/user_spec.rb +++ b/spec/integration/user_spec.rb @@ -28,13 +28,14 @@ } end - it_should_behave_like 'a resource' - it_should_behave_like 'a resource with a singular GET endpoint' + it_behaves_like 'a resource' + it_behaves_like 'a resource with a singular GET endpoint' describe '#all' do let(:client) do client = double(options: { rest_base_path: '/jira/rest/api/2' }) - allow(client).to receive(:get).with('/rest/api/2/users/search?username=_&maxResults=1000').and_return(JIRA::Resource::UserFactory.new(client)) + allow(client).to receive(:get).with('/rest/api/2/users/search?username=_&maxResults=1000') + .and_return(JIRA::Resource::UserFactory.new(client)) client end @@ -47,7 +48,7 @@ it 'gets users with maxResults of 1000' do expect(client).to receive(:get).with('/rest/api/2/users/search?username=_&maxResults=1000') expect(client).to receive_message_chain(:User, :build).with('User1') - JIRA::Resource::User.all(client) + described_class.all(client) end end end diff --git a/spec/integration/version_spec.rb b/spec/integration/version_spec.rb index bd24ac26..e4abf5c1 100644 --- a/spec/integration/version_spec.rb +++ b/spec/integration/version_spec.rb @@ -10,7 +10,7 @@ let(:expected_attributes) do { 'self' => 'http://localhost:2990/jira/rest/api/2/version/10000', - 'id' => key, + 'id' => key, 'description' => 'Initial version' } end @@ -29,11 +29,11 @@ { 'id' => '10000', 'name' => '2.0.0' } end - it_should_behave_like 'a resource' - it_should_behave_like 'a resource with a singular GET endpoint' - it_should_behave_like 'a resource with a DELETE endpoint' - it_should_behave_like 'a resource with a POST endpoint' - it_should_behave_like 'a resource with a PUT endpoint' - it_should_behave_like 'a resource with a PUT endpoint that rejects invalid fields' + it_behaves_like 'a resource' + it_behaves_like 'a resource with a singular GET endpoint' + it_behaves_like 'a resource with a DELETE endpoint' + it_behaves_like 'a resource with a POST endpoint' + it_behaves_like 'a resource with a PUT endpoint' + it_behaves_like 'a resource with a PUT endpoint that rejects invalid fields' end end diff --git a/spec/integration/watcher_spec.rb b/spec/integration/watcher_spec.rb index 3edb5813..00fa199b 100644 --- a/spec/integration/watcher_spec.rb +++ b/spec/integration/watcher_spec.rb @@ -5,7 +5,7 @@ let(:client) { client } let(:site_url) { site_url } - let(:target) { JIRA::Resource::Watcher.new(client, attrs: { 'id' => '99999' }, issue_id: '10002') } + let(:target) { described_class.new(client, attrs: { 'id' => '99999' }, issue_id: '10002') } let(:belongs_to) do JIRA::Resource::Issue.new(client, attrs: { @@ -19,44 +19,43 @@ let(:expected_attributes) do { 'self' => 'http://localhost:2990/jira/rest/api/2/issue/10002/watchers', - "isWatching": false, - "watchCount": 1, - "watchers": [ + isWatching: false, + watchCount: 1, + watchers: [ { - "self": 'http://www.example.com/jira/rest/api/2/user?username=admin', - "name": 'admin', - "displayName": 'admin', - "active": false + self: 'http://www.example.com/jira/rest/api/2/user?username=admin', + name: 'admin', + displayName: 'admin', + active: false } ] } end describe 'watchers' do - before(:each) do - stub_request(:get, site_url + '/jira/rest/api/2/issue/10002') + before do + stub_request(:get, "#{site_url}/jira/rest/api/2/issue/10002") .to_return(status: 200, body: get_mock_response('issue/10002.json')) - stub_request(:get, site_url + '/jira/rest/api/2/issue/10002/watchers') + stub_request(:get, "#{site_url}/jira/rest/api/2/issue/10002/watchers") .to_return(status: 200, body: get_mock_response('issue/10002/watchers.json')) - stub_request(:post, site_url + '/jira/rest/api/2/issue/10002/watchers') + stub_request(:post, "#{site_url}/jira/rest/api/2/issue/10002/watchers") .to_return(status: 204, body: nil) end - it 'should returns all the watchers' do + it 'returnses all the watchers' do issue = client.Issue.find('10002') - watchers = client.Watcher.all(options = { issue: issue }) + watchers = client.Watcher.all(options = { issue: }) expect(watchers.length).to eq(1) end - it 'should add a watcher' do + it 'adds a watcher' do issue = client.Issue.find('10002') - watcher = JIRA::Resource::Watcher.new(client, issue: issue) - user_id = "tester" + watcher = described_class.new(client, issue:) + user_id = 'tester' watcher.save!(user_id) end end - end end diff --git a/spec/integration/webhook.rb b/spec/integration/webhook.rb index 2c53278b..f5ce76f9 100644 --- a/spec/integration/webhook.rb +++ b/spec/integration/webhook.rb @@ -8,14 +8,15 @@ let(:key) { '2' } let(:expected_attributes) do - { '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' => 1_453_306_520_188 } + { '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' => 1_453_306_520_188 } end let(:expected_collection_length) { 1 } - it_should_behave_like 'a resource' - it_should_behave_like 'a resource with a collection GET endpoint' - it_should_behave_like 'a resource with a singular GET endpoint' + it_behaves_like 'a resource' + it_behaves_like 'a resource with a collection GET endpoint' + it_behaves_like 'a resource with a singular GET endpoint' it 'returns a collection of components' do stub_request(:get, site_url + described_class.singular_path(client, key)) diff --git a/spec/integration/worklog_spec.rb b/spec/integration/worklog_spec.rb index 15ff7b0f..46c896a4 100644 --- a/spec/integration/worklog_spec.rb +++ b/spec/integration/worklog_spec.rb @@ -7,7 +7,7 @@ let(:key) { '10000' } - let(:target) { JIRA::Resource::Worklog.new(client, attrs: { 'id' => '99999' }, issue_id: '54321') } + let(:target) { described_class.new(client, attrs: { 'id' => '99999' }, issue_id: '54321') } let(:expected_collection_length) { 3 } @@ -22,7 +22,7 @@ let(:expected_attributes) do { 'self' => 'http://localhost:2990/jira/rest/api/2/issue/10002/worklog/10000', - 'id' => key, + 'id' => key, 'comment' => 'Some epic work.' } end @@ -41,11 +41,11 @@ { 'id' => '10001', 'timeSpent' => '4d' } end - it_should_behave_like 'a resource' - it_should_behave_like 'a resource with a collection GET endpoint' - it_should_behave_like 'a resource with a singular GET endpoint' - it_should_behave_like 'a resource with a DELETE endpoint' - it_should_behave_like 'a resource with a POST endpoint' - it_should_behave_like 'a resource with a PUT endpoint' + it_behaves_like 'a resource' + it_behaves_like 'a resource with a collection GET endpoint' + it_behaves_like 'a resource with a singular GET endpoint' + it_behaves_like 'a resource with a DELETE endpoint' + it_behaves_like 'a resource with a POST endpoint' + it_behaves_like 'a resource with a PUT endpoint' end end diff --git a/spec/jira/base_factory_spec.rb b/spec/jira/base_factory_spec.rb index 991d67e1..636b6ecb 100644 --- a/spec/jira/base_factory_spec.rb +++ b/spec/jira/base_factory_spec.rb @@ -4,9 +4,10 @@ class JIRA::Resource::FooFactory < JIRA::BaseFactory; end class JIRA::Resource::Foo; end - let(:client) { double } subject { JIRA::Resource::FooFactory.new(client) } + let(:client) { double } + it 'initializes correctly' do expect(subject.class).to eq(JIRA::Resource::FooFactory) expect(subject.client).to eq(client) diff --git a/spec/jira/base_spec.rb b/spec/jira/base_spec.rb index 0833a940..0089a406 100644 --- a/spec/jira/base_spec.rb +++ b/spec/jira/base_spec.rb @@ -32,11 +32,11 @@ class JIRA::Resource::HasManyExample < JIRA::Base # :nodoc: attribute_key: 'irregularlyNamedThings' end + subject { JIRA::Resource::Deadbeef.new(client, attrs:) } + let(:client) { double('client') } let(:attrs) { {} } - subject { JIRA::Resource::Deadbeef.new(client, attrs: attrs) } - let(:decorated) { JIRADelegation.new(subject) } describe '#respond_to?' do @@ -44,6 +44,7 @@ class JIRA::Resource::HasManyExample < JIRA::Base # :nodoc: it 'responds to client' do expect(decorated.respond_to?(:client)).to eq(true) end + it 'does not raise an error' do expect do decorated.respond_to?(:client) @@ -125,7 +126,7 @@ class JIRA::Resource::HasManyExample < JIRA::Base # :nodoc: end describe 'collection_path' do - before(:each) do + before do expect(client).to receive(:options).and_return(rest_base_path: '/deadbeef/bar') end @@ -147,8 +148,9 @@ class JIRA::Resource::HasManyExample < JIRA::Base # :nodoc: end describe 'dynamic instance methods' do + subject { JIRA::Resource::Deadbeef.new(client, attrs:) } + let(:attrs) { { 'foo' => 'bar', 'flum' => 'goo', 'object_id' => 'dummy' } } - subject { JIRA::Resource::Deadbeef.new(client, attrs: attrs) } it 'responds to each of the top level attribute names' do expect(subject).to respond_to(:foo) @@ -169,7 +171,7 @@ class JIRA::Resource::HasManyExample < JIRA::Base # :nodoc: subject { JIRA::Resource::Deadbeef.new(client, attrs: { 'id' => '98765' }) } describe 'not cached' do - before(:each) do + before do response = instance_double('Response', body: '{"self":"http://deadbeef/","id":"98765"}') expect(client).to receive(:get).with('/jira/rest/api/2/deadbeef/98765').and_return(response) expect(JIRA::Resource::Deadbeef).to receive(:collection_path).and_return('/jira/rest/api/2/deadbeef') @@ -222,17 +224,17 @@ class JIRA::Resource::HasManyExample < JIRA::Base # :nodoc: end describe 'save' do - let(:response) { double } - subject { JIRA::Resource::Deadbeef.new(client) } - before(:each) do + let(:response) { double } + + before do expect(subject).to receive(:url).and_return('/foo/bar') end it 'POSTs a new record' do response = instance_double('Response', body: '{"id":"123"}') - allow(subject).to receive(:new_record?) { true } + allow(subject).to receive(:new_record?).and_return(true) expect(client).to receive(:post).with('/foo/bar', '{"foo":"bar"}').and_return(response) expect(subject.save('foo' => 'bar')).to be_truthy expect(subject.id).to eq('123') @@ -241,7 +243,7 @@ class JIRA::Resource::HasManyExample < JIRA::Base # :nodoc: it 'PUTs an existing record' do response = instance_double('Response', body: nil) - allow(subject).to receive(:new_record?) { false } + allow(subject).to receive(:new_record?).and_return(false) expect(client).to receive(:put).with('/foo/bar', '{"foo":"bar"}').and_return(response) expect(subject.save('foo' => 'bar')).to be_truthy expect(subject.expanded).to be_falsey @@ -255,14 +257,17 @@ class JIRA::Resource::HasManyExample < JIRA::Base # :nodoc: expect(subject.foo).to eq('bar' => 'baz', 'fum' => 'dum') end - it 'returns false when an invalid field is set' do # The JIRA REST API apparently ignores fields that you aren't allowed to set manually + it 'returns false when an invalid field is set' do + # The JIRA REST API apparently ignores fields that you aren't allowed to set manually response = instance_double('Response', body: '{"errorMessages":["blah"]}', status: 400) - allow(subject).to receive(:new_record?) { false } - expect(client).to receive(:put).with('/foo/bar', '{"invalid_field":"foobar"}').and_raise(JIRA::HTTPError.new(response)) + allow(subject).to receive(:new_record?).and_return(false) + expect(client).to receive(:put).with('/foo/bar', + '{"invalid_field":"foobar"}').and_raise(JIRA::HTTPError.new(response)) expect(subject.save('invalid_field' => 'foobar')).to be_falsey end - it 'returns false with exception details when non json response body (unauthorized)' do # Unauthorized requests return a non-json body. This makes sure we can handle non-json bodies on HTTPError + it 'returns false with exception details when non json response body (unauthorized)' do + # Unauthorized requests return a non-json body. This makes sure we can handle non-json bodies on HTTPError response = double('Response', body: 'totally invalid json', code: 401, message: 'Unauthorized') expect(client).to receive(:post).with('/foo/bar', '{"foo":"bar"}').and_raise(JIRA::HTTPError.new(response)) expect(subject.save('foo' => 'bar')).to be_falsey @@ -272,17 +277,17 @@ class JIRA::Resource::HasManyExample < JIRA::Base # :nodoc: end describe 'save!' do - let(:response) { double } - subject { JIRA::Resource::Deadbeef.new(client) } - before(:each) do + let(:response) { double } + + before do expect(subject).to receive(:url).and_return('/foo/bar') end it 'POSTs a new record' do response = instance_double('Response', body: '{"id":"123"}') - allow(subject).to receive(:new_record?) { true } + allow(subject).to receive(:new_record?).and_return(true) expect(client).to receive(:post).with('/foo/bar', '{"foo":"bar"}').and_return(response) expect(subject.save!('foo' => 'bar')).to be_truthy expect(subject.id).to eq('123') @@ -291,7 +296,7 @@ class JIRA::Resource::HasManyExample < JIRA::Base # :nodoc: it 'PUTs an existing record' do response = instance_double('Response', body: nil) - allow(subject).to receive(:new_record?) { false } + allow(subject).to receive(:new_record?).and_return(false) expect(client).to receive(:put).with('/foo/bar', '{"foo":"bar"}').and_return(response) expect(subject.save!('foo' => 'bar')).to be_truthy expect(subject.expanded).to be_falsey @@ -299,9 +304,10 @@ class JIRA::Resource::HasManyExample < JIRA::Base # :nodoc: it 'throws an exception when an invalid field is set' do response = instance_double('Response', body: '{"errorMessages":["blah"]}', status: 400) - allow(subject).to receive(:new_record?) { false } - expect(client).to receive(:put).with('/foo/bar', '{"invalid_field":"foobar"}').and_raise(JIRA::HTTPError.new(response)) - expect{ subject.save!('invalid_field' => 'foobar') }.to raise_error(JIRA::HTTPError) + allow(subject).to receive(:new_record?).and_return(false) + expect(client).to receive(:put).with('/foo/bar', + '{"invalid_field":"foobar"}').and_raise(JIRA::HTTPError.new(response)) + expect { subject.save!('invalid_field' => 'foobar') }.to raise_error(JIRA::HTTPError) end end @@ -320,9 +326,9 @@ class JIRA::Resource::HasManyExample < JIRA::Base # :nodoc: end describe 'delete' do - before(:each) do + before do expect(client).to receive(:delete).with('/foo/bar') - allow(subject).to receive(:url) { '/foo/bar' } + allow(subject).to receive(:url).and_return('/foo/bar') end it 'flags itself as deleted' do @@ -360,8 +366,8 @@ class JIRA::Resource::HasManyExample < JIRA::Base # :nodoc: end describe 'url' do - before(:each) do - allow(client).to receive(:options) { { rest_base_path: '/foo/bar' } } + before do + allow(client).to receive(:options).and_return({ rest_base_path: '/foo/bar' }) end it 'returns self as the URL if set' do @@ -370,13 +376,13 @@ class JIRA::Resource::HasManyExample < JIRA::Base # :nodoc: end it 'returns path as the URL if set and site options is specified' do - allow(client).to receive(:options) { { site: 'http://foo' } } + allow(client).to receive(:options).and_return({ site: 'http://foo' }) attrs['self'] = 'http://foo/bar' expect(subject.url).to eq('/bar') end it 'returns path as the URL if set and site options is specified and ends with a slash' do - allow(client).to receive(:options) { { site: 'http://foo/' } } + allow(client).to receive(:options).and_return({ site: 'http://foo/' }) attrs['self'] = 'http://foo/bar' expect(subject.url).to eq('/bar') end @@ -487,7 +493,9 @@ class JIRA::Resource::HasManyExample < JIRA::Base # :nodoc: end it 'allows the has_many attributes to be nested inside another attribute' do - subject = JIRA::Resource::HasManyExample.new(client, attrs: { 'nested' => { 'brunchmuffins' => [{ 'id' => '123' }, { 'id' => '456' }] } }) + subject = JIRA::Resource::HasManyExample.new(client, + attrs: { 'nested' => { 'brunchmuffins' => [{ 'id' => '123' }, + { 'id' => '456' }] } }) expect(subject.brunchmuffins.length).to eq(2) subject.brunchmuffins.each do |brunchmuffin| expect(brunchmuffin.class).to eq(JIRA::Resource::Deadbeef) @@ -495,9 +503,12 @@ class JIRA::Resource::HasManyExample < JIRA::Base # :nodoc: end it 'allows it to be deeply nested' do - subject = JIRA::Resource::HasManyExample.new(client, attrs: { 'nested' => { - 'breakfastscone' => { 'breakfastscones' => [{ 'id' => '123' }, { 'id' => '456' }] } - } }) + subject = JIRA::Resource::HasManyExample.new( + client, + attrs: { + 'nested' => { 'breakfastscone' => { 'breakfastscones' => [{ 'id' => '123' }, { 'id' => '456' }] } } + } + ) expect(subject.breakfastscones.length).to eq(2) subject.breakfastscones.each do |breakfastscone| expect(breakfastscone.class).to eq(JIRA::Resource::Deadbeef) @@ -512,7 +523,9 @@ class JIRA::Resource::HasManyExample < JIRA::Base # :nodoc: end it 'allows the attribute key to be specified' do - subject = JIRA::Resource::HasManyExample.new(client, attrs: { 'irregularlyNamedThings' => [{ 'id' => '123' }, { 'id' => '456' }] }) + subject = JIRA::Resource::HasManyExample.new(client, + attrs: { 'irregularlyNamedThings' => [{ 'id' => '123' }, + { 'id' => '456' }] }) expect(subject.irregularly_named_things.length).to eq(2) subject.irregularly_named_things.each do |thing| expect(thing.class).to eq(JIRA::Resource::Deadbeef) @@ -545,7 +558,8 @@ class JIRA::Resource::HasManyExample < JIRA::Base # :nodoc: end it 'allows the has_one attributes to be nested inside another attribute' do - subject = JIRA::Resource::HasOneExample.new(client, attrs: { 'nested' => { 'brunchmuffin' => { 'id' => '123' } } }) + subject = JIRA::Resource::HasOneExample.new(client, + attrs: { 'nested' => { 'brunchmuffin' => { 'id' => '123' } } }) expect(subject.brunchmuffin.class).to eq(JIRA::Resource::Deadbeef) expect(subject.brunchmuffin.id).to eq('123') end @@ -570,27 +584,27 @@ class JIRA::Resource::BelongsToExample < JIRA::Base belongs_to :deadbeef end - let(:deadbeef) { JIRA::Resource::Deadbeef.new(client, attrs: { 'id' => '999' }) } + subject { JIRA::Resource::BelongsToExample.new(client, attrs: { 'id' => '123' }, deadbeef:) } - subject { JIRA::Resource::BelongsToExample.new(client, attrs: { 'id' => '123' }, deadbeef: deadbeef) } + let(:deadbeef) { JIRA::Resource::Deadbeef.new(client, attrs: { 'id' => '999' }) } it 'sets up an accessor for the belongs to relationship' do expect(subject.deadbeef).to eq(deadbeef) end it 'raises an exception when initialized without a belongs_to instance' do - expect{ + expect do JIRA::Resource::BelongsToExample.new(client, attrs: { 'id' => '123' }) - }.to raise_exception(ArgumentError, 'Required option :deadbeef missing') + end.to raise_exception(ArgumentError, 'Required option :deadbeef missing') end it 'returns the right url' do - allow(client).to receive(:options) { { rest_base_path: '/foo' } } + allow(client).to receive(:options).and_return({ rest_base_path: '/foo' }) expect(subject.url).to eq('/foo/deadbeef/999/belongstoexample/123') end it 'can be initialized with an instance or a key value' do - allow(client).to receive(:options) { { rest_base_path: '/foo' } } + allow(client).to receive(:options).and_return({ rest_base_path: '/foo' }) subject = JIRA::Resource::BelongsToExample.new(client, attrs: { 'id' => '123' }, deadbeef_id: '987') expect(subject.url).to eq('/foo/deadbeef/987/belongstoexample/123') end diff --git a/spec/jira/client_spec.rb b/spec/jira/client_spec.rb index dfd04948..0014862b 100644 --- a/spec/jira/client_spec.rb +++ b/spec/jira/client_spec.rb @@ -28,7 +28,7 @@ expect(subject).to receive(:merge_default_headers).exactly(3).times.with({}) # response for merging headers for http methods with body - expect(subject).to receive(:merge_default_headers).exactly(2).times.with(content_type_header) + expect(subject).to receive(:merge_default_headers).twice.with(content_type_header) %i[delete get head].each { |method| subject.send(method, '/path', {}) } %i[post put].each { |method| subject.send(method, '/path', '', content_type_header) } @@ -62,13 +62,20 @@ describe 'SSL client options' do context 'without certificate and key' do - let(:options) { { use_client_cert: true } } subject { JIRA::Client.new(options) } + let(:options) { { use_client_cert: true } } + it 'raises an ArgumentError' do - expect { subject }.to raise_exception(ArgumentError, 'Options: :cert_path or :ssl_client_cert must be set when :use_client_cert is true') + expect do + subject + end.to raise_exception(ArgumentError, + 'Options: :cert_path or :ssl_client_cert must be set when :use_client_cert is true') options[:ssl_client_cert] = '' - expect { subject }.to raise_exception(ArgumentError, 'Options: :key_path or :ssl_client_key must be set when :use_client_cert is true') + expect do + subject + end.to raise_exception(ArgumentError, + 'Options: :key_path or :ssl_client_key must be set when :use_client_cert is true') end end end @@ -77,11 +84,13 @@ RSpec.shared_examples 'HttpClient tests' do it 'makes a valid request' do %i[delete get head].each do |method| - expect(subject.request_client).to receive(:make_request).with(method, '/path', nil, headers).and_return(successful_response) + expect(subject.request_client).to receive(:make_request).with(method, '/path', nil, + headers).and_return(successful_response) subject.send(method, '/path', headers) end %i[post put].each do |method| - expect(subject.request_client).to receive(:make_request).with(method, '/path', '', merged_headers).and_return(successful_response) + expect(subject.request_client).to receive(:make_request).with(method, '/path', '', + merged_headers).and_return(successful_response) subject.send(method, '/path', '', headers) end end @@ -106,11 +115,13 @@ describe 'that call a oauth client' do specify 'which makes a request' do %i[delete get head].each do |method| - expect(subject.request_client).to receive(:make_request).with(method, '/path', nil, headers).and_return(successful_response) + expect(subject.request_client).to receive(:make_request).with(method, '/path', nil, + headers).and_return(successful_response) subject.send(method, '/path', {}) end %i[post put].each do |method| - expect(subject.request_client).to receive(:make_request).with(method, '/path', '', merged_headers).and_return(successful_response) + expect(subject.request_client).to receive(:make_request).with(method, '/path', '', + merged_headers).and_return(successful_response) subject.send(method, '/path', '', {}) end end @@ -130,22 +141,22 @@ context 'behaviour that applies to all client classes irrespective of authentication method' do it 'allows the overriding of some options' do - client = JIRA::Client.new(consumer_key: 'foo', consumer_secret: 'bar', site: 'http://foo.com/') + client = described_class.new(consumer_key: 'foo', consumer_secret: 'bar', site: 'http://foo.com/') expect(client.options[:site]).to eq('http://foo.com/') expect(JIRA::Client::DEFAULT_OPTIONS[:site]).not_to eq('http://foo.com/') end end context 'with basic http authentication' do - subject { JIRA::Client.new(username: 'foo', password: 'bar', auth_type: :basic) } + subject { described_class.new(username: 'foo', password: 'bar', auth_type: :basic) } - before(:each) do + before do stub_request(:get, 'https://localhost:2990/jira/rest/api/2/project') .with(headers: { 'Authorization' => "Basic #{Base64.strict_encode64('foo:bar').chomp}" }) .to_return(status: 200, body: '[]', headers: {}) stub_request(:get, 'https://localhost:2990/jira/rest/api/2/project') - .with(headers: { 'Authorization' => "Basic #{Base64.strict_encode64('foo:badpassword').chomp}" }) + .with(headers: { 'Authorization' => "Basic #{Base64.strict_encode64('foo:badpassword').chomp}" }) .to_return(status: 401, headers: {}) end @@ -166,26 +177,26 @@ end it 'fails with wrong user name and password' do - bad_login = JIRA::Client.new(username: 'foo', password: 'badpassword', auth_type: :basic) + bad_login = described_class.new(username: 'foo', password: 'badpassword', auth_type: :basic) expect(bad_login.authenticated?).to be_falsey expect { bad_login.Project.all }.to raise_error JIRA::HTTPError end end context 'with cookie authentication' do - subject { JIRA::Client.new(username: 'foo', password: 'bar', auth_type: :cookie) } + subject { described_class.new(username: 'foo', password: 'bar', auth_type: :cookie) } let(:session_cookie) { '6E3487971234567896704A9EB4AE501F' } let(:session_body) do { - 'session': { 'name' => 'JSESSIONID', 'value' => session_cookie }, - 'loginInfo': { 'failedLoginCount' => 1, 'loginCount' => 2, + session: { 'name' => 'JSESSIONID', 'value' => session_cookie }, + loginInfo: { 'failedLoginCount' => 1, 'loginCount' => 2, 'lastFailedLoginTime' => (DateTime.now - 2).iso8601, 'previousLoginTime' => (DateTime.now - 5).iso8601 } } end - before(:each) do + before do # General case of API call with no authentication, or wrong authentication stub_request(:post, 'https://localhost:2990/jira/rest/auth/1/session') .to_return(status: 401, headers: {}) @@ -212,7 +223,7 @@ end it 'does not authenticate with an incorrect username and password' do - bad_client = JIRA::Client.new(username: 'foo', password: 'bad_password', auth_type: :cookie) + bad_client = described_class.new(username: 'foo', password: 'bad_password', auth_type: :cookie) expect(bad_client).not_to be_authenticated end @@ -224,7 +235,7 @@ context 'with jwt authentication' do subject do - JIRA::Client.new( + described_class.new( issuer: 'foo', base_url: 'https://host.tld', shared_secret: 'shared_secret_key', @@ -232,10 +243,10 @@ ) end - before(:each) do + before do stub_request(:get, 'https://localhost:2990/jira/rest/api/2/project') - .with(headers: {"Authorization" => /JWT .+/}) - .to_return(status: 200, body: '[]', headers: {}) + .with(headers: { 'Authorization' => /JWT .+/ }) + .to_return(status: 200, body: '[]', headers: {}) end include_examples 'Client Common Tests' @@ -250,8 +261,8 @@ context 'with a incorrect jwt key' do before do stub_request(:get, 'https://localhost:2990/jira/rest/api/2/project') - .with(headers: {"Authorization" => /JWT .+/}) - .to_return(status: 401, body: '[]', headers: {}) + .with(headers: { 'Authorization' => /JWT .+/ }) + .to_return(status: 401, body: '[]', headers: {}) end it 'is not authenticated' do @@ -271,20 +282,21 @@ end context 'oauth authentication' do - subject { JIRA::Client.new(consumer_key: 'foo', consumer_secret: 'bar') } + subject { described_class.new(consumer_key: 'foo', consumer_secret: 'bar') } include_examples 'OAuth Common Tests' end context 'with oauth_2legged' do - subject { JIRA::Client.new(consumer_key: 'foo', consumer_secret: 'bar', auth_type: :oauth_2legged) } + subject { described_class.new(consumer_key: 'foo', consumer_secret: 'bar', auth_type: :oauth_2legged) } include_examples 'OAuth Common Tests' end context 'with unknown options' do + subject { described_class.new(options) } + let(:options) { { 'username' => 'foo', 'password' => 'bar', auth_type: :basic } } - subject { JIRA::Client.new(options) } it 'raises an ArgumentError' do expect { subject }.to raise_exception(ArgumentError, 'Unknown option(s) given: ["username", "password"]') diff --git a/spec/jira/has_many_proxy_spec.rb b/spec/jira/has_many_proxy_spec.rb index d3979aa9..ac2ea2da 100644 --- a/spec/jira/has_many_proxy_spec.rb +++ b/spec/jira/has_many_proxy_spec.rb @@ -3,7 +3,7 @@ describe JIRA::HasManyProxy do class Foo; end - subject { JIRA::HasManyProxy.new(parent, Foo, collection) } + subject { described_class.new(parent, Foo, collection) } let(:parent) { double('parent') } let(:collection) { double('collection') } @@ -25,7 +25,7 @@ class Foo; end foo = double('foo') allow(parent).to receive(:client).and_return(client) allow(parent).to receive(:to_sym).and_return(:parent) - expect(Foo).to receive(:new).with(client, attrs: { 'foo' => 'bar' }, parent: parent).and_return(foo) + expect(Foo).to receive(:new).with(client, attrs: { 'foo' => 'bar' }, parent:).and_return(foo) expect(collection).to receive(:<<).with(foo) expect(subject.build('foo' => 'bar')).to eq(foo) end @@ -35,7 +35,7 @@ class Foo; end client = double('client') allow(parent).to receive(:client).and_return(client) allow(parent).to receive(:to_sym).and_return(:parent) - expect(Foo).to receive(:all).with(client, parent: parent).and_return(foo) + expect(Foo).to receive(:all).with(client, parent:).and_return(foo) expect(subject.all).to eq(foo) end diff --git a/spec/jira/http_client_spec.rb b/spec/jira/http_client_spec.rb index 9a0a96da..5ad17eaa 100644 --- a/spec/jira/http_client_spec.rb +++ b/spec/jira/http_client_spec.rb @@ -5,7 +5,7 @@ options = JIRA::Client::DEFAULT_OPTIONS .merge(JIRA::HttpClient::DEFAULT_OPTIONS) .merge(basic_auth_credentials) - JIRA::HttpClient.new(options) + described_class.new(options) end let(:basic_cookie_client) do @@ -13,12 +13,12 @@ .merge(JIRA::HttpClient::DEFAULT_OPTIONS) .merge(use_cookies: true) .merge(basic_auth_credentials) - JIRA::HttpClient.new(options) + described_class.new(options) end let(:custom_ssl_version_client) do options = JIRA::Client::DEFAULT_OPTIONS.merge(JIRA::HttpClient::DEFAULT_OPTIONS).merge(ssl_version: :TLSv1_2) - JIRA::HttpClient.new(options) + described_class.new(options) end let(:basic_cookie_client_with_context_path) do @@ -26,7 +26,7 @@ use_cookies: true, context_path: '/context' ) - JIRA::HttpClient.new(options) + described_class.new(options) end let(:basic_cookie_client_with_additional_cookies) do @@ -37,7 +37,7 @@ additional_cookies: ['sessionToken=abc123', 'internal=true'] ) .merge(basic_auth_credentials) - JIRA::HttpClient.new(options) + described_class.new(options) end let(:basic_client_cert_client) do @@ -46,13 +46,13 @@ cert: 'public certificate contents', key: 'private key contents' ) - JIRA::HttpClient.new(options) + described_class.new(options) end let(:basic_client_with_no_auth_credentials) do options = JIRA::Client::DEFAULT_OPTIONS .merge(JIRA::HttpClient::DEFAULT_OPTIONS) - JIRA::HttpClient.new(options) + described_class.new(options) end let(:basic_auth_credentials) do @@ -66,14 +66,14 @@ proxy_username: 'proxyUsername', proxy_password: 'proxyPassword' ) - JIRA::HttpClient.new(options) + described_class.new(options) end let(:basic_client_with_max_retries) do options = JIRA::Client::DEFAULT_OPTIONS.merge(JIRA::HttpClient::DEFAULT_OPTIONS).merge( max_retries: 2 ) - JIRA::HttpClient.new(options) + described_class.new(options) end let(:response) do @@ -96,19 +96,17 @@ proxy_username: 'proxyUsername', proxy_password: 'proxyPassword' ) - JIRA::HttpClient.new(options_local) + described_class.new(options_local) end describe 'HttpClient#basic_auth_http_conn' do subject(:http_conn) { basic_client.basic_auth_http_conn } it 'creates an instance of Net:HTTP for a basic auth client' do - expect(http_conn.class).to eq(Net::HTTP) end it 'the connection created has no proxy' do - http_conn expect(http_conn.proxy_address).to be_nil @@ -149,7 +147,8 @@ basic_auth_http_conn = double request = double allow(basic_client).to receive(:basic_auth_http_conn).and_return(basic_auth_http_conn) - expect(request).to receive(:basic_auth).with(basic_client.options[:username], basic_client.options[:password]).exactly(5).times.and_return(request) + expect(request).to receive(:basic_auth).with(basic_client.options[:username], + basic_client.options[:password]).exactly(5).times.and_return(request) expect(basic_auth_http_conn).to receive(:request).exactly(5).times.with(request).and_return(response) %i[delete get head].each do |method| expect(Net::HTTP.const_get(method.to_s.capitalize)).to receive(:new).with('/path', headers).and_return(request) @@ -168,7 +167,8 @@ basic_auth_http_conn = double request = double allow(basic_cookie_client).to receive(:basic_auth_http_conn).and_return(basic_auth_http_conn) - expect(request).to receive(:basic_auth).with(basic_cookie_client.options[:username], basic_cookie_client.options[:password]).exactly(5).times.and_return(request) + expect(request).to receive(:basic_auth).with(basic_cookie_client.options[:username], + basic_cookie_client.options[:password]).exactly(5).times.and_return(request) expect(cookie_response).to receive(:get_fields).with('set-cookie').exactly(5).times expect(basic_auth_http_conn).to receive(:request).exactly(5).times.with(request).and_return(cookie_response) %i[delete get head].each do |method| @@ -189,7 +189,8 @@ basic_auth_http_conn = double request = double allow(client).to receive(:basic_auth_http_conn).and_return(basic_auth_http_conn) - expect(request).to receive(:basic_auth).with(client.options[:username], client.options[:password]).exactly(5).times.and_return(request) + expect(request).to receive(:basic_auth).with(client.options[:username], + client.options[:password]).exactly(5).times.and_return(request) expect(request).to receive(:add_field).with('Cookie', 'sessionToken=abc123; internal=true').exactly(5).times expect(cookie_response).to receive(:get_fields).with('set-cookie').exactly(5).times expect(basic_auth_http_conn).to receive(:request).exactly(5).times.with(request).and_return(cookie_response) @@ -212,7 +213,8 @@ expect(Net::HTTP::Get).to receive(:new).with('/foo', headers).and_return(http_request) expect(basic_auth_http_conn).to receive(:request).with(http_request).and_return(response) - expect(http_request).to receive(:basic_auth).with(basic_client.options[:username], basic_client.options[:password]).and_return(http_request) + expect(http_request).to receive(:basic_auth).with(basic_client.options[:username], + basic_client.options[:password]).and_return(http_request) allow(basic_client).to receive(:basic_auth_http_conn).and_return(basic_auth_http_conn) basic_client.make_request(:get, '/foo', body, headers) end @@ -225,7 +227,8 @@ expect(Net::HTTP::Get).to receive(:new).with('/foo', headers).and_return(http_request) expect(basic_auth_http_conn).to receive(:request).with(http_request).and_return(response) - expect(http_request).to receive(:basic_auth).with(basic_client.options[:username], basic_client.options[:password]).and_return(http_request) + expect(http_request).to receive(:basic_auth).with(basic_client.options[:username], + basic_client.options[:password]).and_return(http_request) allow(basic_client).to receive(:basic_auth_http_conn).and_return(basic_auth_http_conn) basic_client.make_request(:get, 'http://mydomain.com/foo', body, headers) end @@ -293,6 +296,8 @@ end context 'client has proxy settings' do + subject(:proxy_conn) { proxy_client.basic_auth_http_conn } + let(:proxy_client) do options_local = JIRA::Client::DEFAULT_OPTIONS.merge(JIRA::HttpClient::DEFAULT_OPTIONS).merge( proxy_address: 'proxyAddress', @@ -300,13 +305,11 @@ proxy_username: 'proxyUsername', proxy_password: 'proxyPassword' ) - JIRA::HttpClient.new(options_local) + described_class.new(options_local) end - subject(:proxy_conn) { proxy_client.basic_auth_http_conn } describe 'HttpClient#basic_auth_http_conn' do it 'creates a Net:HTTP instance for a basic auth client setting up a proxied http connection' do - expect(proxy_conn.class).to eq(Net::HTTP) expect(proxy_conn.proxy_address).to eq(proxy_client.options[:proxy_address]) @@ -334,7 +337,7 @@ end it 'can use a certificate authority file' do - client = JIRA::HttpClient.new(JIRA::Client::DEFAULT_OPTIONS.merge(ca_file: '/opt/custom.ca.pem')) + client = described_class.new(JIRA::Client::DEFAULT_OPTIONS.merge(ca_file: '/opt/custom.ca.pem')) expect(client.http_conn(client.uri).ca_file).to eql('/opt/custom.ca.pem') end @@ -370,7 +373,7 @@ let(:data) { {} } let(:headers) { { 'X-Atlassian-Token' => 'no-check' } } let(:basic_auth_http_conn) { double } - let(:request) { double('Http Request', path: path) } + let(:request) { double('Http Request', path:) } let(:response) { double('response') } before do @@ -381,7 +384,8 @@ end it 'performs a basic http client request' do - expect(request).to receive(:basic_auth).with(basic_client.options[:username], basic_client.options[:password]).and_return(request) + expect(request).to receive(:basic_auth).with(basic_client.options[:username], + basic_client.options[:password]).and_return(request) subject end diff --git a/spec/jira/http_error_spec.rb b/spec/jira/http_error_spec.rb index a94120b2..c2ddf1d7 100644 --- a/spec/jira/http_error_spec.rb +++ b/spec/jira/http_error_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe JIRA::HTTPError do + subject { described_class.new(response) } + let(:response) do response = double('response') allow(response).to receive(:code).and_return(401) @@ -8,8 +10,6 @@ response end - subject { described_class.new(response) } - it 'takes the response object as an argument' do expect(subject.response).to eq(response) end diff --git a/spec/jira/oauth_client_spec.rb b/spec/jira/oauth_client_spec.rb index 165443e8..5666b6c6 100644 --- a/spec/jira/oauth_client_spec.rb +++ b/spec/jira/oauth_client_spec.rb @@ -4,7 +4,7 @@ let(:oauth_client) do options = { consumer_key: 'foo', consumer_secret: 'bar' } options = JIRA::Client::DEFAULT_OPTIONS.merge(options) - JIRA::OauthClient.new(options) + described_class.new(options) end let(:response) do @@ -124,7 +124,6 @@ it 'performs a request' do expect(access_token).to receive(:send).with(:get, '/foo', headers).and_return(response) - oauth_client.request(:get, '/foo', body, headers) end @@ -136,7 +135,8 @@ it 'signs the access_token and performs the request' do expect(access_token).to receive(:sign!).with(an_instance_of(Net::HTTP::Post::Multipart)) - expect(oauth_client.consumer).to receive_message_chain(:http, :request).with(an_instance_of(Net::HTTP::Post::Multipart)) + expect(oauth_client.consumer).to receive_message_chain(:http, + :request).with(an_instance_of(Net::HTTP::Post::Multipart)) subject end @@ -147,7 +147,7 @@ let(:oauth__2legged_client) do options = { consumer_key: 'foo', consumer_secret: 'bar', auth_type: :oauth_2legged } options = JIRA::Client::DEFAULT_OPTIONS.merge(options) - JIRA::OauthClient.new(options) + described_class.new(options) end it 'responds to the http methods adding oauth_token parameter' do @@ -169,11 +169,13 @@ mock_access_token = double allow(oauth__2legged_client).to receive(:access_token).and_return(mock_access_token) %i[delete get head].each do |method| - expect(mock_access_token).to receive(method).with('/path?any_param=toto&oauth_token=', headers).and_return(response) + expect(mock_access_token).to receive(method).with('/path?any_param=toto&oauth_token=', + headers).and_return(response) oauth__2legged_client.make_request(method, '/path?any_param=toto', '', headers) end %i[post put].each do |method| - expect(mock_access_token).to receive(method).with('/path?any_param=toto&oauth_token=', '', headers).and_return(response) + expect(mock_access_token).to receive(method).with('/path?any_param=toto&oauth_token=', '', + headers).and_return(response) oauth__2legged_client.make_request(method, '/path?any_param=toto', '', headers) end end diff --git a/spec/jira/request_client_spec.rb b/spec/jira/request_client_spec.rb index 1de1fcee..416253a2 100644 --- a/spec/jira/request_client_spec.rb +++ b/spec/jira/request_client_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe JIRA::RequestClient do - let(:request_client) { JIRA::RequestClient.new } + let(:request_client) { described_class.new } describe '#request' do subject(:request) { request_client.request(:get, '/foo', '', {}) } @@ -15,7 +15,7 @@ end it 'raises an exception' do - expect{ subject }.to raise_exception(JIRA::HTTPError) + expect { subject }.to raise_exception(JIRA::HTTPError) end end end @@ -34,8 +34,8 @@ end it 'raises an exception' do - expect{ subject }.to raise_exception(JIRA::HTTPError) + expect { subject }.to raise_exception(JIRA::HTTPError) end end end -end \ No newline at end of file +end diff --git a/spec/jira/resource/agile_spec.rb b/spec/jira/resource/agile_spec.rb index 6b488df3..c0502634 100644 --- a/spec/jira/resource/agile_spec.rb +++ b/spec/jira/resource/agile_spec.rb @@ -9,34 +9,34 @@ let(:response) { double } describe '#all' do - it 'should query url without parameters' do + it 'queries url without parameters' do expect(client).to receive(:get).with('/jira/rest/agile/1.0/board').and_return(response) expect(response).to receive(:body).and_return(get_mock_response('board/1.json')) - JIRA::Resource::Agile.all(client) + described_class.all(client) end end describe '#get_backlog_issues' do - it 'should query the url without parameters' do + it 'queries the url without parameters' do expect(client).to receive(:get).with('/jira/rest/agile/1.0/board/1/backlog?maxResults=100').and_return(response) expect(response).to receive(:body).and_return(get_mock_response('board/1.json')) - JIRA::Resource::Agile.get_backlog_issues(client, 1) + described_class.get_backlog_issues(client, 1) end end describe '#get_board_issues' do - it 'should query correct url without parameters' do + it 'queries correct url without parameters' do expect(client).to receive(:get).with('/jira/rest/agile/1.0/board/1/issue?').and_return(response) expect(response).to receive(:body).and_return(get_mock_response('board/1_issues.json')) expect(client).to receive(:get).with('/jira/rest/api/2/search?jql=id+IN%2810546%2C+10547%2C+10556%2C+10557%2C+10558%2C+10559%2C+10600%2C+10601%2C+10604%29').and_return(response) expect(response).to receive(:body).and_return(get_mock_response('board/1_issues.json')) - issues = JIRA::Resource::Agile.get_board_issues(client, 1) + issues = described_class.get_board_issues(client, 1) expect(issues).to be_an(Array) - expect(issues.size).to eql(9) + expect(issues.size).to be(9) issues.each do |issue| expect(issue.class).to eq(JIRA::Resource::Issue) @@ -44,16 +44,16 @@ end end - it 'should query correct url with parameters' do + it 'queries correct url with parameters' do expect(client).to receive(:get).with('/jira/rest/agile/1.0/board/1/issue?startAt=50').and_return(response) expect(response).to receive(:body).and_return(get_mock_response('board/1_issues.json')) expect(client).to receive(:get).with('/jira/rest/api/2/search?jql=id+IN%2810546%2C+10547%2C+10556%2C+10557%2C+10558%2C+10559%2C+10600%2C+10601%2C+10604%29').and_return(response) expect(response).to receive(:body).and_return(get_mock_response('board/1_issues.json')) - issues = JIRA::Resource::Agile.get_board_issues(client, 1, startAt: 50) + issues = described_class.get_board_issues(client, 1, startAt: 50) expect(issues).to be_an(Array) - expect(issues.size).to eql(9) + expect(issues.size).to be(9) issues.each do |issue| expect(issue.class).to eq(JIRA::Resource::Issue) @@ -63,73 +63,73 @@ end describe '#get_sprints' do - it 'should query correct url without parameters' do + it 'queries correct url without parameters' do expect(client).to receive(:get).with('/jira/rest/agile/1.0/board/1/sprint?maxResults=100').and_return(response) expect(response).to receive(:body).and_return(get_mock_response('board/1.json')) - JIRA::Resource::Agile.get_sprints(client, 1) + described_class.get_sprints(client, 1) end - it 'should query correct url with parameters' do + it 'queries correct url with parameters' do expect(client).to receive(:get).with('/jira/rest/agile/1.0/board/1/sprint?startAt=50&maxResults=100').and_return(response) expect(response).to receive(:body).and_return(get_mock_response('board/1.json')) - JIRA::Resource::Agile.get_sprints(client, 1, startAt: 50) + described_class.get_sprints(client, 1, startAt: 50) end - it 'should work with pagination starting at 0' do + it 'works with pagination starting at 0' do expect(client).to receive(:get).with('/jira/rest/agile/1.0/board/1/sprint?maxResults=1&startAt=0').and_return(response) expect(response).to receive(:body).and_return(get_mock_response('board/1.json')) - JIRA::Resource::Agile.get_sprints(client, 1, maxResults: 1, startAt: 0) + described_class.get_sprints(client, 1, maxResults: 1, startAt: 0) end - it 'should work with pagination not starting at 0' do + it 'works with pagination not starting at 0' do expect(client).to receive(:get).with('/jira/rest/agile/1.0/board/1/sprint?maxResults=1&startAt=1').and_return(response) expect(response).to receive(:body).and_return(get_mock_response('board/1.json')) - JIRA::Resource::Agile.get_sprints(client, 1, maxResults: 1, startAt: 1) + described_class.get_sprints(client, 1, maxResults: 1, startAt: 1) end end describe '#get_sprint_issues' do - it 'should query correct url without parameters' do + it 'queries correct url without parameters' do expect(client).to receive(:get).with('/jira/rest/agile/1.0/sprint/1/issue?maxResults=100').and_return(response) expect(response).to receive(:body).and_return(get_mock_response('sprint/1_issues.json')) - JIRA::Resource::Agile.get_sprint_issues(client, 1) + described_class.get_sprint_issues(client, 1) end - it 'should query correct url with parameters' do + it 'queries correct url with parameters' do expect(client).to receive(:get).with('/jira/rest/agile/1.0/sprint/1/issue?startAt=50&maxResults=100').and_return(response) expect(response).to receive(:body).and_return(get_mock_response('sprint/1_issues.json')) - JIRA::Resource::Agile.get_sprint_issues(client, 1, startAt: 50) + described_class.get_sprint_issues(client, 1, startAt: 50) end end describe '#get_projects_full' do - it 'should query correct url without parameters' do + it 'queries correct url without parameters' do expect(client).to receive(:get).with('/jira/rest/agile/1.0/board/1/project/full').and_return(response) expect(response).to receive(:body).and_return(get_mock_response('board/1.json')) - JIRA::Resource::Agile.get_projects_full(client, 1) + described_class.get_projects_full(client, 1) end end describe '#get_projects' do - it 'should query correct url without parameters' do + it 'queries correct url without parameters' do expect(client).to receive(:get).with('/jira/rest/agile/1.0/board/1/project?maxResults=100').and_return(response) expect(response).to receive(:body).and_return(get_mock_response('board/1.json')) - JIRA::Resource::Agile.get_projects(client, 1) + described_class.get_projects(client, 1) end - it 'should query correct url with parameters' do + it 'queries correct url with parameters' do expect(client).to receive(:get).with('/jira/rest/agile/1.0/board/1/project?startAt=50&maxResults=100').and_return(response) expect(response).to receive(:body).and_return(get_mock_response('board/1.json')) - JIRA::Resource::Agile.get_projects(client, 1, startAt: 50) + described_class.get_projects(client, 1, startAt: 50) end end end diff --git a/spec/jira/resource/attachment_spec.rb b/spec/jira/resource/attachment_spec.rb index a1783be9..b213461a 100644 --- a/spec/jira/resource/attachment_spec.rb +++ b/spec/jira/resource/attachment_spec.rb @@ -2,7 +2,7 @@ describe JIRA::Resource::Attachment do subject(:attachment) do - JIRA::Resource::Attachment.new( + described_class.new( client, issue: JIRA::Resource::Issue.new(client), attrs: { 'author' => { 'foo' => 'bar' } } @@ -35,7 +35,7 @@ end describe '.meta' do - subject { JIRA::Resource::Attachment.meta(client) } + subject { described_class.meta(client) } let(:response) do double( @@ -60,20 +60,21 @@ end context 'there is an attachment on an issue' do - let(:client) do - JIRA::Client.new(username: 'username', password: 'password', auth_type: :basic, use_ssl: false) - end - let(:attachment_file_contents) { 'file contents' } - let(:attachment_url) { 'https://localhost:2990/secure/attachment/32323/myfile.txt' } subject(:attachment) do - JIRA::Resource::Attachment.new( + described_class.new( client, issue: JIRA::Resource::Issue.new(client), attrs: { 'author' => { 'foo' => 'bar' }, 'content' => attachment_url } ) end - before(:each) do + let(:client) do + JIRA::Client.new(username: 'username', password: 'password', auth_type: :basic, use_ssl: false) + end + let(:attachment_file_contents) { 'file contents' } + let(:attachment_url) { 'https://localhost:2990/secure/attachment/32323/myfile.txt' } + + before do stub_request(:get, attachment_url).to_return(body: attachment_file_contents) end @@ -104,12 +105,12 @@ double( body: [ { - "id": 10_001, - "self": 'http://www.example.com/jira/rest/api/2.0/attachments/10000', - "filename": file_name, - "created": '2017-07-19T12:23:06.572+0000', - "size": file_size, - "mimeType": file_mime_type + id: 10_001, + self: 'http://www.example.com/jira/rest/api/2.0/attachments/10000', + filename: file_name, + created: '2017-07-19T12:23:06.572+0000', + size: file_size, + mimeType: file_mime_type } ].to_json ) @@ -130,22 +131,24 @@ expect(attachment.mimeType).to eq file_mime_type expect(attachment.size).to eq file_size end + context 'when using custom client headers' do subject(:bearer_attachment) do - JIRA::Resource::Attachment.new( + described_class.new( bearer_client, issue: JIRA::Resource::Issue.new(bearer_client), attrs: { 'author' => { 'foo' => 'bar' } } ) end - let(:default_headers_given) { + + let(:default_headers_given) do { 'authorization' => 'Bearer 83CF8B609DE60036A8277BD0E96135751BBC07EB234256D4B65B893360651BF2' } - } + end let(:bearer_client) do JIRA::Client.new(username: 'username', password: 'password', auth_type: :basic, use_ssl: false, - default_headers: default_headers_given ) + default_headers: default_headers_given) end let(:merged_headers) do { @@ -193,16 +196,17 @@ context 'when using custom client headers' do subject(:bearer_attachment) do - JIRA::Resource::Attachment.new( + described_class.new( bearer_client, issue: JIRA::Resource::Issue.new(bearer_client), attrs: { 'author' => { 'foo' => 'bar' } } ) end + let(:default_headers_given) { { 'authorization' => 'Bearer 83CF8B609DE60036A8277BD0E96135751BBC07EB234256D4B65B893360651BF2' } } let(:bearer_client) do JIRA::Client.new(username: 'username', password: 'password', auth_type: :basic, use_ssl: false, - default_headers: default_headers_given ) + default_headers: default_headers_given) end let(:merged_headers) do { diff --git a/spec/jira/resource/board_spec.rb b/spec/jira/resource/board_spec.rb index 288889e6..229b174f 100644 --- a/spec/jira/resource/board_spec.rb +++ b/spec/jira/resource/board_spec.rb @@ -25,12 +25,12 @@ class JIRAResourceDelegation < SimpleDelegator # :nodoc: .and_return(response) expect(client).to receive(:Board).and_return(JIRA::Resource::BoardFactory.new(client)) - JIRA::Resource::Board.find(client, '84') + described_class.find(client, '84') end - it 'should find all boards' do + it 'finds all boards' do response = double - api_json = < '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' => 10_666 } }), - JIRA::Resource::Field.new(client, attrs: { 'id' => 'issuekey', 'name' => 'Key', 'custom' => false, 'orderable' => false, 'navigable' => true, 'searchable' => false, 'clauseNames' => %w[id issue issuekey key] }), - 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' } }), - 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' } }), - JIRA::Resource::Field.new(client, attrs: { 'id' => 'issuetype', 'name' => 'Issue Type', 'custom' => false, 'orderable' => true, 'navigable' => true, 'searchable' => true, 'clauseNames' => %w[issuetype type], 'schema' => { 'type' => 'issuetype', 'system' => 'issuetype' } }), - 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' => 10_111 } }), - 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' => 10_222 } }), - 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' => 10_333 } }), - 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' => 10_444 } }) + described_class.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' => 10_666 } }), + described_class.new(client, + attrs: { 'id' => 'issuekey', 'name' => 'Key', 'custom' => false, 'orderable' => false, + 'navigable' => true, 'searchable' => false, 'clauseNames' => %w[id issue issuekey key] }), + described_class.new(client, + attrs: { 'id' => 'priority', 'name' => 'Priority', 'custom' => false, 'orderable' => true, + 'navigable' => true, 'searchable' => true, 'clauseNames' => ['priority'], 'schema' => { 'type' => 'priority', 'system' => 'priority' } }), + described_class.new(client, + attrs: { 'id' => 'summary', 'name' => 'Summary', 'custom' => false, 'orderable' => true, + 'navigable' => true, 'searchable' => true, 'clauseNames' => ['summary'], 'schema' => { 'type' => 'string', 'system' => 'summary' } }), + described_class.new(client, + attrs: { 'id' => 'issuetype', 'name' => 'Issue Type', 'custom' => false, 'orderable' => true, + 'navigable' => true, 'searchable' => true, 'clauseNames' => %w[issuetype type], 'schema' => { 'type' => 'issuetype', 'system' => 'issuetype' } }), + described_class.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' => 10_111 } }), + described_class.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' => 10_222 } }), + described_class.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' => 10_333 } }), + described_class.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' => 10_444 } }) ]) client end @@ -26,14 +44,14 @@ describe 'field_mappings' do shared_context 'mapped or not' do subject do - JIRA::Resource::Field.new(client, attrs: { - 'priority' => 1, + described_class.new(client, attrs: { + 'priority' => 1, 'customfield_10111' => 'data_in_custom_field', 'customfield_10222' => 'multi word custom name', 'customfield_10333' => 'complex custom name', 'customfield_10444' => 'duplicated custom name', 'customfield_10666' => 'duplicate of a system name' - }) + }) end it 'can find a standard field by id' do diff --git a/spec/jira/resource/filter_spec.rb b/spec/jira/resource/filter_spec.rb index 20ef909a..58117f51 100644 --- a/spec/jira/resource/filter_spec.rb +++ b/spec/jira/resource/filter_spec.rb @@ -49,8 +49,8 @@ end let(:filter) do expect(client).to receive(:get).with("#{collection_path}/42").and_return(filter_response) - allow(JIRA::Resource::Filter).to receive(:collection_path).and_return(collection_path) - JIRA::Resource::Filter.find(client, 42) + allow(described_class).to receive(:collection_path).and_return(collection_path) + described_class.find(client, 42) end let(:jql_issue) do { @@ -90,7 +90,7 @@ .and_return(issue_jql_response) issues = filter.issues expect(issues).to be_an(Array) - expect(issues.size).to eql(1) + expect(issues.size).to be(1) expected_issue = client.Issue.build(JSON.parse(jql_issue.to_json)) expect(issues.first.attrs).to eql(expected_issue.attrs) end diff --git a/spec/jira/resource/issue_picker_suggestions_spec.rb b/spec/jira/resource/issue_picker_suggestions_spec.rb index 6cbc3512..d398dc7d 100644 --- a/spec/jira/resource/issue_picker_suggestions_spec.rb +++ b/spec/jira/resource/issue_picker_suggestions_spec.rb @@ -3,15 +3,15 @@ describe JIRA::Resource::IssuePickerSuggestions do let(:client) do double('client', options: { - rest_base_path: '/jira/rest/api/2' - }) + rest_base_path: '/jira/rest/api/2' + }) end describe 'relationships' do subject do - JIRA::Resource::IssuePickerSuggestions.new(client, attrs: { - 'sections' => [{ 'id' => 'hs'}, { 'id' => 'cs' }] - }) + described_class.new(client, attrs: { + 'sections' => [{ 'id' => 'hs' }, { 'id' => 'cs' }] + }) end it 'has the correct relationships' do @@ -30,7 +30,7 @@ allow(issue_picker_suggestions).to receive(:build) end - it 'should autocomplete issues' do + it 'autocompletes issues' do allow(response).to receive(:body).and_return('{"sections":[{"id": "cs"}]}') expect(client).to receive(:get).with('/jira/rest/api/2/issue/picker?query=query') .and_return(response) @@ -38,42 +38,42 @@ expect(client).to receive(:IssuePickerSuggestions).and_return(issue_picker_suggestions) expect(issue_picker_suggestions).to receive(:build).with({ 'sections' => [{ 'id' => 'cs' }] }) - JIRA::Resource::IssuePickerSuggestions.all(client, 'query') + described_class.all(client, 'query') end - it 'should autocomplete issues with current jql' do + it 'autocompletes issues with current jql' do expect(client).to receive(:get).with('/jira/rest/api/2/issue/picker?query=query¤tJQL=project+%3D+PR') .and_return(response) - JIRA::Resource::IssuePickerSuggestions.all(client, 'query', current_jql: 'project = PR') + described_class.all(client, 'query', current_jql: 'project = PR') end - it 'should autocomplete issues with current issue jey' do + it 'autocompletes issues with current issue jey' do expect(client).to receive(:get).with('/jira/rest/api/2/issue/picker?query=query¤tIssueKey=PR-42') .and_return(response) - JIRA::Resource::IssuePickerSuggestions.all(client, 'query', current_issue_key: 'PR-42') + described_class.all(client, 'query', current_issue_key: 'PR-42') end - it 'should autocomplete issues with current project id' do + it 'autocompletes issues with current project id' do expect(client).to receive(:get).with('/jira/rest/api/2/issue/picker?query=query¤tProjectId=PR') .and_return(response) - JIRA::Resource::IssuePickerSuggestions.all(client, 'query', current_project_id: 'PR') + described_class.all(client, 'query', current_project_id: 'PR') end - it 'should autocomplete issues with show sub tasks' do + it 'autocompletes issues with show sub tasks' do expect(client).to receive(:get).with('/jira/rest/api/2/issue/picker?query=query&showSubTasks=true') .and_return(response) - JIRA::Resource::IssuePickerSuggestions.all(client, 'query', show_sub_tasks: true) + described_class.all(client, 'query', show_sub_tasks: true) end - it 'should autocomplete issues with show sub tasks parent' do + it 'autocompletes issues with show sub tasks parent' do expect(client).to receive(:get).with('/jira/rest/api/2/issue/picker?query=query&showSubTaskParent=true') .and_return(response) - JIRA::Resource::IssuePickerSuggestions.all(client, 'query', show_sub_task_parent: true) + described_class.all(client, 'query', show_sub_task_parent: true) end end end diff --git a/spec/jira/resource/issue_spec.rb b/spec/jira/resource/issue_spec.rb index 9fbcb5d2..2943ab1d 100644 --- a/spec/jira/resource/issue_spec.rb +++ b/spec/jira/resource/issue_spec.rb @@ -13,19 +13,21 @@ class JIRAResourceDelegation < SimpleDelegator # :nodoc: describe '#respond_to?' do describe 'when decorated by SimpleDelegator' do - before(:each) do + before do response = double allow(response).to receive(:body).and_return('{"key":"foo","id":"101"}') - allow(JIRA::Resource::Issue).to receive(:collection_path).and_return('/jira/rest/api/2/issue') + allow(described_class).to receive(:collection_path).and_return('/jira/rest/api/2/issue') allow(client).to receive(:get).with('/jira/rest/api/2/issue/101') .and_return(response) - issue = JIRA::Resource::Issue.find(client, 101) + issue = described_class.find(client, 101) @decorated = JIRAResourceDelegation.new(issue) end + it 'responds to key' do expect(@decorated.respond_to?(:key)).to eq(true) end + it 'does not raise an error' do expect do @issue.respond_to?(:project) @@ -34,7 +36,7 @@ class JIRAResourceDelegation < SimpleDelegator # :nodoc: end end - it 'should find all issues' do + it 'finds all issues' do response = double empty_response = double issue = double @@ -49,26 +51,26 @@ class JIRAResourceDelegation < SimpleDelegator # :nodoc: expect(client).to receive(:Issue).and_return(issue) expect(issue).to receive(:build).with({ 'id' => '1', 'summary' => 'Bugs Everywhere' }) - issues = JIRA::Resource::Issue.all(client) + issues = described_class.all(client) end - it 'should find an issue by key or id' do + it 'finds an issue by key or id' do response = double allow(response).to receive(:body).and_return('{"key":"foo","id":"101"}') - allow(JIRA::Resource::Issue).to receive(:collection_path).and_return('/jira/rest/api/2/issue') + allow(described_class).to receive(:collection_path).and_return('/jira/rest/api/2/issue') expect(client).to receive(:get).with('/jira/rest/api/2/issue/foo') .and_return(response) expect(client).to receive(:get).with('/jira/rest/api/2/issue/101') .and_return(response) - issue_from_id = JIRA::Resource::Issue.find(client, 101) - issue_from_key = JIRA::Resource::Issue.find(client, 'foo') + issue_from_id = described_class.find(client, 101) + issue_from_key = described_class.find(client, 'foo') expect(issue_from_id.attrs).to eq(issue_from_key.attrs) end - it 'should search an issue with a jql query string' do + it 'searches an issue with a jql query string' do response = double issue = double @@ -78,10 +80,10 @@ class JIRAResourceDelegation < SimpleDelegator # :nodoc: expect(client).to receive(:Issue).and_return(issue) expect(issue).to receive(:build).with(%w[key foo]).and_return('') - expect(JIRA::Resource::Issue.jql(client, 'foo bar')).to eq(['']) + expect(described_class.jql(client, 'foo bar')).to eq(['']) end - it 'should search an issue with a jql query string and fields' do + it 'searches an issue with a jql query string and fields' do response = double issue = double @@ -92,10 +94,10 @@ class JIRAResourceDelegation < SimpleDelegator # :nodoc: expect(client).to receive(:Issue).and_return(issue) expect(issue).to receive(:build).with(%w[key foo]).and_return('') - expect(JIRA::Resource::Issue.jql(client, 'foo bar', fields: %w[foo bar])).to eq(['']) + expect(described_class.jql(client, 'foo bar', fields: %w[foo bar])).to eq(['']) end - it 'should search an issue with a jql query string, start at, and maxResults' do + it 'searches an issue with a jql query string, start at, and maxResults' do response = double issue = double @@ -106,10 +108,10 @@ class JIRAResourceDelegation < SimpleDelegator # :nodoc: expect(client).to receive(:Issue).and_return(issue) expect(issue).to receive(:build).with(%w[key foo]).and_return('') - expect(JIRA::Resource::Issue.jql(client, 'foo bar', start_at: 1, max_results: 3)).to eq(['']) + expect(described_class.jql(client, 'foo bar', start_at: 1, max_results: 3)).to eq(['']) end - it 'should search an issue with a jql query string and maxResults equals zero and should return the count of tickets' do + it 'searches an issue with a jql query string and maxResults equals zero and should return the count of tickets' do response = double issue = double @@ -118,10 +120,10 @@ class JIRAResourceDelegation < SimpleDelegator # :nodoc: .with('/jira/rest/api/2/search?jql=foo+bar&maxResults=0') .and_return(response) - expect(JIRA::Resource::Issue.jql(client, 'foo bar', max_results: 0)).to eq(1) + expect(described_class.jql(client, 'foo bar', max_results: 0)).to eq(1) end - it 'should search an issue with a jql query string and string expand' do + it 'searches an issue with a jql query string and string expand' do response = double issue = double @@ -132,10 +134,10 @@ class JIRAResourceDelegation < SimpleDelegator # :nodoc: expect(client).to receive(:Issue).and_return(issue) expect(issue).to receive(:build).with(%w[key foo]).and_return('') - expect(JIRA::Resource::Issue.jql(client, 'foo bar', expand: 'transitions')).to eq(['']) + expect(described_class.jql(client, 'foo bar', expand: 'transitions')).to eq(['']) end - it 'should search an issue with a jql query string and array expand' do + it 'searches an issue with a jql query string and array expand' do response = double issue = double @@ -146,11 +148,11 @@ class JIRAResourceDelegation < SimpleDelegator # :nodoc: expect(client).to receive(:Issue).and_return(issue) expect(issue).to receive(:build).with(%w[key foo]).and_return('') - expect(JIRA::Resource::Issue.jql(client, 'foo bar', expand: %w[transitions])).to eq(['']) + expect(described_class.jql(client, 'foo bar', expand: %w[transitions])).to eq(['']) end - it 'should return meta data available for editing an issue' do - subject = JIRA::Resource::Issue.new(client, attrs: { 'fields' => { 'key' => 'TST=123' } }) + it 'returns meta data available for editing an issue' do + subject = described_class.new(client, attrs: { 'fields' => { 'key' => 'TST=123' } }) response = double allow(response).to receive(:body).and_return( @@ -164,30 +166,30 @@ class JIRAResourceDelegation < SimpleDelegator # :nodoc: end it 'provides direct accessors to the fields' do - subject = JIRA::Resource::Issue.new(client, attrs: { 'fields' => { 'foo' => 'bar' } }) + subject = described_class.new(client, attrs: { 'fields' => { 'foo' => 'bar' } }) expect(subject).to respond_to(:foo) expect(subject.foo).to eq('bar') end describe 'relationships' do subject do - JIRA::Resource::Issue.new(client, attrs: { - 'id' => '123', + described_class.new(client, attrs: { + 'id' => '123', 'fields' => { 'reporter' => { 'foo' => 'bar' }, - 'assignee' => { 'foo' => 'bar' }, - 'project' => { 'foo' => 'bar' }, - 'priority' => { 'foo' => 'bar' }, - 'issuetype' => { 'foo' => 'bar' }, - 'status' => { 'foo' => 'bar' }, - 'resolution' => { 'foo' => 'bar' }, - 'components' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }], - 'versions' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }], - 'comment' => { 'comments' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }] }, - 'attachment' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }], - 'worklog' => { 'worklogs' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }] } + 'assignee' => { 'foo' => 'bar' }, + 'project' => { 'foo' => 'bar' }, + 'priority' => { 'foo' => 'bar' }, + 'issuetype' => { 'foo' => 'bar' }, + 'status' => { 'foo' => 'bar' }, + 'resolution' => { 'foo' => 'bar' }, + 'components' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }], + 'versions' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }], + 'comment' => { 'comments' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }] }, + 'attachment' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }], + 'worklog' => { 'worklogs' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }] } } - }) + }) end it 'has the correct relationships' do diff --git a/spec/jira/resource/jira_picker_suggestions_issue_spec.rb b/spec/jira/resource/jira_picker_suggestions_issue_spec.rb index c584b87a..44e4afb5 100644 --- a/spec/jira/resource/jira_picker_suggestions_issue_spec.rb +++ b/spec/jira/resource/jira_picker_suggestions_issue_spec.rb @@ -5,9 +5,9 @@ describe 'relationships' do subject do - JIRA::Resource::IssuePickerSuggestionsIssue.new(client, attrs: { - 'issues' => [{ 'id' => '1'}, { 'id' => '2' }] - }) + described_class.new(client, attrs: { + 'issues' => [{ 'id' => '1' }, { 'id' => '2' }] + }) end it 'has the correct relationships' do diff --git a/spec/jira/resource/project_factory_spec.rb b/spec/jira/resource/project_factory_spec.rb index 50b9c827..a4989cad 100644 --- a/spec/jira/resource/project_factory_spec.rb +++ b/spec/jira/resource/project_factory_spec.rb @@ -1,11 +1,12 @@ require 'spec_helper' describe JIRA::Resource::ProjectFactory do + subject { described_class.new(client) } + let(:client) { double } - subject { JIRA::Resource::ProjectFactory.new(client) } it 'initializes correctly' do - expect(subject.class).to eq(JIRA::Resource::ProjectFactory) + expect(subject.class).to eq(described_class) expect(subject.client).to eq(client) end end diff --git a/spec/jira/resource/project_spec.rb b/spec/jira/resource/project_spec.rb index df8e102b..67e83abe 100644 --- a/spec/jira/resource/project_spec.rb +++ b/spec/jira/resource/project_spec.rb @@ -9,11 +9,11 @@ describe 'relationships' do subject do - JIRA::Resource::Project.new(client, attrs: { - 'lead' => { 'foo' => 'bar' }, - 'issueTypes' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }], - 'versions' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }] - }) + described_class.new(client, attrs: { + 'lead' => { 'foo' => 'bar' }, + 'issueTypes' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }], + 'versions' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }] + }) end it 'has the correct relationships' do @@ -30,13 +30,13 @@ describe 'issues' do subject do - JIRA::Resource::Project.new(client, attrs: { - 'key' => 'test' - }) + described_class.new(client, attrs: { + 'key' => 'test' + }) end it 'returns issues' do - response_body = '{"expand":"schema,names","startAt":0,"maxResults":1,"total":1,"issues":[{"expand":"editmeta,renderedFields,transitions,changelog,operations","id":"53062","self":"/rest/api/2/issue/53062","key":"test key","fields":{"summary":"test summary"}}]}' + response_body = '{"expand":"schema,names","startAt":0,"maxResults":1,"total":1,"issues":[{"expand":"editmeta,renderedFields,transitions,changelog,operations","id":"53062","self":"/rest/api/2/issue/53062","key":"test key","fields":{"summary":"test summary"}}]}' # rubocop:disable Layout/LineLength response = double('response', body: response_body) issue_factory = double('issue factory') @@ -52,7 +52,7 @@ context 'with changelog' do it 'returns issues' do - response_body = '{"expand":"schema,names","startAt":0,"maxResults":1,"total":1,"issues":[{"expand":"editmeta,renderedFields,transitions,changelog,operations","id":"53062","self":"/rest/api/2/issue/53062","key":"test key","fields":{"summary":"test summary"},"changelog":{}}]}' + response_body = '{"expand":"schema,names","startAt":0,"maxResults":1,"total":1,"issues":[{"expand":"editmeta,renderedFields,transitions,changelog,operations","id":"53062","self":"/rest/api/2/issue/53062","key":"test key","fields":{"summary":"test summary"},"changelog":{}}]}' # rubocop:disable Layout/LineLength response = double('response', body: response_body) issue_factory = double('issue factory') @@ -69,12 +69,12 @@ end describe 'users' do - let(:project) { JIRA::Resource::Project.new(client, attrs: { 'key' => project_key }) } + let(:project) { described_class.new(client, attrs: { 'key' => project_key }) } let(:project_key) { SecureRandom.hex } let(:response) { double('response', body: '[{}]') } context 'pagination' do - before(:each) do + before do user_factory = double('user factory') expect(client).to receive(:User).and_return(user_factory) expect(user_factory).to receive(:build).with(any_args) @@ -95,7 +95,7 @@ .with("/jira/rest/api/2/user/assignable/search?project=#{project_key}&startAt=#{start_at}") .and_return(response) - project.users(start_at: start_at) + project.users(start_at:) end it 'accepts max_results option' do @@ -105,7 +105,7 @@ .with("/jira/rest/api/2/user/assignable/search?project=#{project_key}&maxResults=#{max_results}") .and_return(response) - project.users(max_results: max_results) + project.users(max_results:) end it 'accepts start_at and max_results options' do @@ -113,10 +113,10 @@ max_results = rand(1000) expect(client).to receive(:get) - .with("/jira/rest/api/2/user/assignable/search?project=#{project_key}&startAt=#{start_at}&maxResults=#{max_results}") + .with("/jira/rest/api/2/user/assignable/search?project=#{project_key}&startAt=#{start_at}&maxResults=#{max_results}") # rubocop:disable Layout/LineLength .and_return(response) - project.users(start_at: start_at, max_results: max_results) + project.users(start_at:, max_results:) end end end diff --git a/spec/jira/resource/sprint_spec.rb b/spec/jira/resource/sprint_spec.rb index ca57fd3c..3041280a 100644 --- a/spec/jira/resource/sprint_spec.rb +++ b/spec/jira/resource/sprint_spec.rb @@ -11,7 +11,8 @@ let(:response) { double } describe 'get_sprint_details' do - let(:sprint) { JIRA::Resource::Sprint.find(client, '1') } + let(:sprint) { described_class.find(client, '1') } + it 'check each of the date attributes' do allow(client).to receive(:get).and_return(double(body: get_mock_response('sprint/1.json'))) @@ -26,7 +27,7 @@ it 'fetches the sprint from JIRA' do expect(client).to receive(:get).with('/jira/rest/agile/1.0/sprint/111').and_return(response) - expect(JIRA::Resource::Sprint.find(client, '111')).to be_a(JIRA::Resource::Sprint) + expect(described_class.find(client, '111')).to be_a(described_class) end end @@ -111,7 +112,7 @@ issue end let(:post_issue_input) do - { "issues": [issue.id] } + { issues: [issue.id] } end describe '#add_issu' do @@ -126,7 +127,7 @@ end context 'multiple issues exists' do - let(:issue_ids) { [ 1001, 1012 ] } + let(:issue_ids) { [1001, 1012] } let(:post_issue_path) do described_class.agile_path(client, sprint.id) '/jira/rest/agile/1.0/sprint//issue' @@ -139,7 +140,7 @@ end end let(:post_issue_input) do - { "issues": issue_ids } + { issues: issue_ids } end describe '#add_issues' do diff --git a/spec/jira/resource/status_spec.rb b/spec/jira/resource/status_spec.rb index e3023dc6..de2652fe 100644 --- a/spec/jira/resource/status_spec.rb +++ b/spec/jira/resource/status_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' describe JIRA::Resource::Status do - let(:client) do client = double(options: { rest_base_path: '/jira/rest/api/2' }) allow(client).to receive(:Field).and_return(JIRA::Resource::FieldFactory.new(client)) @@ -11,7 +10,7 @@ describe '#status_category' do subject do - JIRA::Resource::Status.new(client, attrs: JSON.parse(File.read('spec/mock_responses/status/1.json'))) + described_class.new(client, attrs: JSON.parse(File.read('spec/mock_responses/status/1.json'))) end it 'has a status_category relationship' do @@ -19,4 +18,4 @@ expect(subject.status_category.name).to eq('To Do') end end -end \ No newline at end of file +end diff --git a/spec/jira/resource/user_factory_spec.rb b/spec/jira/resource/user_factory_spec.rb index c94cbe43..d6f4980a 100644 --- a/spec/jira/resource/user_factory_spec.rb +++ b/spec/jira/resource/user_factory_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper' describe JIRA::Resource::UserFactory do + subject { described_class.new(client) } + let(:client) do instance_double('Client', options: { rest_base_path: '/jira/rest/api/2' }) end - subject { JIRA::Resource::UserFactory.new(client) } - describe '#myself' do let(:response) do instance_double( @@ -16,7 +16,7 @@ let(:user) { subject.myself } - before(:each) do + before do allow(client).to receive(:get).with( '/jira/rest/api/2/myself' ).and_return(response) diff --git a/spec/jira/resource/worklog_spec.rb b/spec/jira/resource/worklog_spec.rb index 4ec0b8ff..02f1dea1 100644 --- a/spec/jira/resource/worklog_spec.rb +++ b/spec/jira/resource/worklog_spec.rb @@ -5,10 +5,10 @@ describe 'relationships' do subject do - JIRA::Resource::Worklog.new(client, issue_id: '99999', attrs: { - 'author' => { 'foo' => 'bar' }, + described_class.new(client, issue_id: '99999', attrs: { + 'author' => { 'foo' => 'bar' }, 'updateAuthor' => { 'foo' => 'bar' } - }) + }) end it 'has the correct relationships' do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 1f215500..76d49c49 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -17,5 +17,6 @@ def get_mock_response(file, value_if_file_not_found = false) File.read(File.join(File.dirname(__FILE__), 'mock_responses/', file)) rescue Errno::ENOENT => e raise e if value_if_file_not_found == false + value_if_file_not_found end diff --git a/spec/support/clients_helper.rb b/spec/support/clients_helper.rb index c022b0fe..344b5302 100644 --- a/spec/support/clients_helper.rb +++ b/spec/support/clients_helper.rb @@ -1,5 +1,5 @@ module ClientsHelper - def with_each_client + def with_each_client(&block) clients = {} oauth_client = JIRA::Client.new(consumer_key: 'foo', consumer_secret: 'bar') @@ -9,8 +9,6 @@ def with_each_client basic_client = JIRA::Client.new(username: 'foo', password: 'bar', auth_type: :basic, use_ssl: false) clients['http://localhost:2990'] = basic_client - clients.each do |site_url, client| - yield site_url, client - end + clients.each(&block) end end diff --git a/spec/support/shared_examples/integration.rb b/spec/support/shared_examples/integration.rb index 1c3e0a17..f2b65344 100644 --- a/spec/support/shared_examples/integration.rb +++ b/spec/support/shared_examples/integration.rb @@ -2,7 +2,7 @@ def get_mock_from_path(method, options = {}) prefix = if defined? belongs_to - belongs_to.path_component + '/' + "#{belongs_to.path_component}/" else '' end @@ -15,8 +15,8 @@ def get_mock_from_path(method, options = {}) described_class.collection_path(client, prefix) end file_path = url.sub(client.options[:rest_base_path], '') - file_path = file_path + '.' + options[:suffix] if options[:suffix] - file_path = file_path + '.' + method.to_s unless method == :get + file_path = "#{file_path}.#{options[:suffix]}" if options[:suffix] + file_path = "#{file_path}.#{method}" unless method == :get value_if_not_found = options.key?(:value_if_not_found) ? options[:value_if_not_found] : false get_mock_response("#{file_path}.json", value_if_not_found) end @@ -33,7 +33,7 @@ def options def prefix prefix = '/' - prefix = belongs_to.path_component + '/' if defined? belongs_to + prefix = "#{belongs_to.path_component}/" if defined? belongs_to prefix end @@ -47,11 +47,11 @@ def build_receiver shared_examples 'a resource' do it 'gracefully handles non-json responses' do - if defined? target - subject = target - else - subject = client.send(class_basename).build(described_class.key_attribute.to_s => '99999') - end + subject = if defined? target + target + else + client.send(class_basename).build(described_class.key_attribute.to_s => '99999') + end stub_request(:put, site_url + subject.url) .to_return(status: 405, body: 'Some HTML') expect(subject.save('foo' => 'bar')).to be_falsey @@ -62,7 +62,7 @@ def build_receiver end shared_examples 'a resource with a collection GET endpoint' do - it 'should get the collection' do + it 'gets the collection' do stub_request(:get, site_url + described_class.collection_path(client)) .to_return(status: 200, body: get_mock_from_path(:get)) collection = build_receiver.all @@ -73,13 +73,10 @@ def build_receiver end shared_examples 'a resource with JQL inputs and a collection GET endpoint' do - it 'should get the collection' do + it 'gets the collection' do stub_request( :get, - site_url + - client.options[:rest_base_path] + - '/search?jql=' + - CGI.escape(jql_query_string) + "#{site_url}#{client.options[:rest_base_path]}/search?jql=#{CGI.escape(jql_query_string)}" ).to_return(status: 200, body: get_mock_response('issue.json')) collection = build_receiver.jql(jql_query_string) @@ -94,7 +91,7 @@ def build_receiver # E.g., for JIRA::Resource::Project, we need to call # client.Project.find() stub_request(:get, site_url + described_class.singular_path(client, key, prefix)) - .to_return(status: 200, body: get_mock_from_path(:get, key: key)) + .to_return(status: 200, body: get_mock_from_path(:get, key:)) subject = client.send(class_basename).find(key, options) expect(subject).to have_attributes(expected_attributes) @@ -104,7 +101,7 @@ def build_receiver # E.g., for JIRA::Resource::Project, we need to call # client.Project.build('key' => 'ABC123') stub_request(:get, site_url + described_class.singular_path(client, key, prefix)) - .to_return(status: 200, body: get_mock_from_path(:get, key: key)) + .to_return(status: 200, body: get_mock_from_path(:get, key:)) subject = build_receiver.build(described_class.key_attribute.to_s => key) subject.fetch @@ -114,7 +111,7 @@ def build_receiver it 'handles a 404' do stub_request(:get, site_url + described_class.singular_path(client, '99999', prefix)) - .to_return(status: 404, body: '{"errorMessages":["' + class_basename + ' Does Not Exist"],"errors": {}}') + .to_return(status: 404, body: "{\"errorMessages\":[\"#{class_basename} Does Not Exist\"],\"errors\": {}}") expect do client.send(class_basename).find('99999', options) end.to raise_exception(JIRA::HTTPError) @@ -148,9 +145,9 @@ def build_receiver shared_examples 'a resource with a PUT endpoint' do it 'saves an existing component' do stub_request(:get, site_url + described_class.singular_path(client, key, prefix)) - .to_return(status: 200, body: get_mock_from_path(:get, key: key)) + .to_return(status: 200, body: get_mock_from_path(:get, key:)) stub_request(:put, site_url + described_class.singular_path(client, key, prefix)) - .to_return(status: 200, body: get_mock_from_path(:put, key: key, value_if_not_found: nil)) + .to_return(status: 200, body: get_mock_from_path(:put, key:, value_if_not_found: nil)) subject = build_receiver.build(described_class.key_attribute.to_s => key) subject.fetch expect(subject.save(attributes_for_put)).to be_truthy @@ -163,9 +160,9 @@ def build_receiver shared_examples 'a resource with a PUT endpoint that rejects invalid fields' do it 'fails to save with an invalid field' do stub_request(:get, site_url + described_class.singular_path(client, key)) - .to_return(status: 200, body: get_mock_from_path(:get, key: key)) + .to_return(status: 200, body: get_mock_from_path(:get, key:)) stub_request(:put, site_url + described_class.singular_path(client, key)) - .to_return(status: 400, body: get_mock_from_path(:put, key: key, suffix: 'invalid')) + .to_return(status: 400, body: get_mock_from_path(:put, key:, suffix: 'invalid')) subject = client.send(class_basename).build(described_class.key_attribute.to_s => key) subject.fetch