diff --git a/.gitignore b/.gitignore index 7825f5b..4b2b4ab 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ test/tmp test/version_tmp tmp examples/william.rb +Gemfile.lock diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..3ffe2b0 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,2 @@ +inherit_from: .rubocop_todo.yml + diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 0000000..9c132f0 --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,47 @@ +# This configuration was generated by `rubocop --auto-gen-config` +# on 2014-09-17 21:23:50 -0400 using RuboCop version 0.26.0. +# The point is for the user to remove these configuration records +# one by one as the offenses are removed from the code base. +# Note that changes in the inspected code, or installation of new +# versions of RuboCop, may require this file to be generated again. + +# Offense count: 1 +# Configuration parameters: CountComments. +Metrics/ClassLength: + Max: 106 + +# Offense count: 36 +# Configuration parameters: AllowURI. +Metrics/LineLength: + Max: 140 + +# Offense count: 1 +# Configuration parameters: CountComments. +Metrics/MethodLength: + Max: 14 + +# Offense count: 1 +Style/AsciiComments: + Enabled: false + +# Offense count: 3 +# Configuration parameters: EnforcedStyle, SupportedStyles. +Style/ClassAndModuleChildren: + Enabled: false + +# Offense count: 15 +Style/Documentation: + Enabled: false + +# Offense count: 1 +Style/DoubleNegation: + Enabled: false + +# Offense count: 3 +Style/Lambda: + Enabled: false + +# Offense count: 6 +# Configuration parameters: MaxSlashes. +Style/RegexpLiteral: + Enabled: false diff --git a/.travis.yml b/.travis.yml index 46029af..fd2b214 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,5 @@ rvm: - 1.9.3 - 2.0.0 + - 2.1.2 + diff --git a/Gemfile b/Gemfile index 9cac099..e9ac5cd 100644 --- a/Gemfile +++ b/Gemfile @@ -11,5 +11,6 @@ gem 'pry' gem 'redcarpet' gem 'yard', '~> 0.8' -gem 'yard-tomdoc', git: 'git://github.com/rubyworks/yard-tomdoc' +gem 'yard-tomdoc' gem 'simplecov', require: false +gem 'rubocop', '~> 0.26.0', require: false diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index 53cecb2..0000000 --- a/Gemfile.lock +++ /dev/null @@ -1,112 +0,0 @@ -GIT - remote: git://github.com/rubyworks/yard-tomdoc - revision: e4b09dcd574718bda91d0f956b4dd83246bda273 - specs: - yard-tomdoc (0.7.1) - tomparse (>= 0.4.0) - yard - -PATH - remote: . - specs: - hyperclient (0.4.0) - faraday (~> 0.8) - faraday_middleware (~> 0.9) - futuroscope (>= 0.0.10) - net-http-digest_auth (~> 1.2) - uri_template (~> 0.5) - -GEM - remote: https://rubygems.org/ - specs: - addressable (2.3.4) - ansi (1.4.3) - coderay (1.0.9) - colorize (0.5.8) - crack (0.3.2) - faraday (0.8.9) - multipart-post (~> 1.2.0) - faraday_middleware (0.9.0) - faraday (>= 0.7.4, < 0.9) - ffi (1.8.1) - formatador (0.2.4) - futuroscope (0.1.6) - gherkin-ruby (0.3.0) - growl (1.0.3) - guard (1.8.0) - formatador (>= 0.2.4) - listen (>= 1.0.0) - lumberjack (>= 1.0.2) - pry (>= 0.9.10) - thor (>= 0.14.6) - guard-minitest (0.5.0) - guard (>= 0.4) - guard-spinach (0.0.2) - guard (>= 1.1) - spinach - listen (1.0.3) - rb-fsevent (>= 0.9.3) - rb-inotify (>= 0.9) - rb-kqueue (>= 0.2) - lumberjack (1.0.3) - metaclass (0.0.1) - method_source (0.8.1) - minitest (3.4.0) - mocha (0.13.3) - metaclass (~> 0.0.1) - multi_json (1.7.2) - multipart-post (1.2.0) - net-http-digest_auth (1.4) - pry (0.9.12.1) - coderay (~> 1.0.5) - method_source (~> 0.8) - slop (~> 3.4) - rack (1.5.2) - rack-test (0.6.2) - rack (>= 1.0) - rake (10.0.4) - rb-fsevent (0.9.3) - rb-inotify (0.9.0) - ffi (>= 0.5.0) - rb-kqueue (0.2.0) - ffi (>= 0.5.0) - redcarpet (2.2.2) - simplecov (0.7.1) - multi_json (~> 1.0) - simplecov-html (~> 0.7.1) - simplecov-html (0.7.1) - slop (3.4.4) - spinach (0.8.2) - colorize (= 0.5.8) - gherkin-ruby (~> 0.3.0) - thor (0.18.1) - tomparse (0.4.2) - turn (0.9.6) - ansi - uri_template (0.7.0) - webmock (1.11.0) - addressable (>= 2.2.7) - crack (>= 0.3.2) - yard (0.8.6.1) - -PLATFORMS - ruby - -DEPENDENCIES - growl - guard - guard-minitest - guard-spinach - hyperclient! - minitest (~> 3.4.0) - mocha (~> 0.13) - pry - rack-test (~> 0.6) - rake - redcarpet - simplecov - spinach - turn (~> 0.9) - webmock (~> 1.8) - yard (~> 0.8) - yard-tomdoc! diff --git a/Guardfile b/Guardfile index 8de532e..aaaadf9 100644 --- a/Guardfile +++ b/Guardfile @@ -1,13 +1,13 @@ guard 'minitest' do - watch(%r|^test/(.*)_test\.rb|) - watch(%r|^lib/(.*)([^/]+)\.rb|) { |m| "test/#{m[1]}#{m[2]}_test.rb" } - watch(%r|^(.*)([^/]+)\.rb|) { |m| "test/#{m[1]}#{m[2]}_test.rb" } - watch(%r|^test/test_helper\.rb|) { "test" } + watch(%r{^test/(.*)_test\.rb}) + watch(%r{^lib/(.*)([^/]+)\.rb}) { |m| "test/#{m[1]}#{m[2]}_test.rb" } + watch(%r{^(.*)([^/]+)\.rb}) { |m| "test/#{m[1]}#{m[2]}_test.rb" } + watch(%r{^test/test_helper\.rb}) { 'test' } end guard 'spinach' do - watch(%r|^features/(.*)\.feature|) - watch(%r|^features/steps/(.*)([^/]+)\.rb|) do |m| + watch(%r{^features/(.*)\.feature}) + watch(%r{^features/steps/(.*)([^/]+)\.rb}) do |m| "features/#{m[1]}#{m[2]}.feature" end end diff --git a/Rakefile b/Rakefile index b580d21..5bc3a61 100644 --- a/Rakefile +++ b/Rakefile @@ -14,13 +14,12 @@ if ENV['COVERAGE'] end require 'yard' -YARD::Config.load_plugin('yard-tomdoc') +YARD::Config.load_plugin('yard-tomdoc') YARD::Rake::YardocTask.new do |t| t.files = ['lib/**/*.rb'] t.options = %w(-r README.md) end - Bundler::GemHelper.install_tasks require 'rake/testtask' @@ -37,4 +36,7 @@ task :spinach do ruby '-S spinach' end -task default: [:test, :spinach] +require 'rubocop/rake_task' +RuboCop::RakeTask.new(:rubocop) + +task default: [:rubocop, :test, :spinach] diff --git a/examples/cyberscore.rb b/examples/cyberscore.rb index dbe70bf..52dcf0e 100644 --- a/examples/cyberscore.rb +++ b/examples/cyberscore.rb @@ -16,7 +16,7 @@ def games end def add_game(name) - client.links.submissions.post({name: name}) + client.links.submissions.post(name: name) end def motd @@ -32,9 +32,10 @@ def method_missing(method, *args, &block) end private + def client - @client ||= Hyperclient::EntryPoint.new 'http://cs-api.heroku.com/api', - {debug: false, headers: {'content-type' => 'application/json'}} + @client ||= Hyperclient::EntryPoint.new 'http://cs-api.heroku.com/api', + debug: false, headers: { 'content-type' => 'application/json' } end end @@ -43,18 +44,17 @@ def print_links(links) if link.is_a?(Array) print_links(link) else - puts %{Found "#{name}" at "#{link.url}" } + puts %(Found "#{name}" at "#{link.url}" ) end end end def print_games(games) games.each do |game| - puts %{Found "#{game.attributes['name']}" } + puts %(Found "#{game.attributes['name']}" ) end end - api = Cyberscore.new puts "Let's inspect the API:" @@ -72,5 +72,5 @@ def print_games(games) print_links(api.links.news.links) puts "\n" -puts "I like games!" +puts 'I like games!' print_games(api.games) diff --git a/examples/hal_shop.rb b/examples/hal_shop.rb index 9c70ff0..1a5e04a 100644 --- a/examples/hal_shop.rb +++ b/examples/hal_shop.rb @@ -4,17 +4,17 @@ def print_resources(resources) resources.each do |name, resource| begin - puts %{Found #{name} at #{resource.url}} + puts %(Found #{name} at #{resource.url}) rescue - puts %{Found #{name}} + puts %(Found #{name}) end end end def print_attributes(attributes) - puts "-----------------------------" + puts '-----------------------------' attributes.each do |attribute, value| - puts %{#{attribute}: #{value}} + puts %(#{attribute}: #{value}) end end @@ -31,9 +31,9 @@ def print_attributes(attributes) puts "Let's see what stats we have:" print_attributes(api.embedded.stats.attributes) -products = api.links["http://hal-shop.heroku.com/rels/products"].resource +products = api.links['http://hal-shop.heroku.com/rels/products'].resource -puts +puts puts "And what's the inventory of products?" puts products.attributes['inventory_size'] diff --git a/features/steps/default_config.rb b/features/steps/default_config.rb index ec53886..8bb441c 100644 --- a/features/steps/default_config.rb +++ b/features/steps/default_config.rb @@ -6,12 +6,12 @@ class Spinach::Features::DefaultConfig < Spinach::FeatureSteps end step 'the request should have been sent with the correct JSON headers' do - assert_requested :get, 'api.example.org', headers: {'Content-Type' => 'application/json', 'Accept' => 'application/json'} + assert_requested :get, 'api.example.org', headers: { 'Content-Type' => 'application/json', 'Accept' => 'application/json' } end step 'I send some data to the API' do - stub_request(:post, "http://api.example.org/posts") - api.links.posts.post({title: 'My first blog post'}) + stub_request(:post, 'http://api.example.org/posts') + assert_equal 200, api.links.posts.post(title: 'My first blog post').status end step 'it should have been encoded as JSON' do diff --git a/features/support/api.rb b/features/support/api.rb index ee61330..77e41a1 100644 --- a/features/support/api.rb +++ b/features/support/api.rb @@ -5,9 +5,9 @@ module API include Spinach::Fixtures before do - stub_request(:any, %r{api.example.org*}).to_return(body: root_response, headers:{'Content-Type' => 'application/json'}) - stub_request(:get, 'api.example.org/posts').to_return(body: posts_response, headers: {'Content-Type' => 'application/json'}) - stub_request(:get, 'api.example.org/posts/1').to_return(body: post_response, headers: {'Content-Type' => 'application/json'}) + stub_request(:any, %r{api.example.org*}).to_return(body: root_response, headers: { 'Content-Type' => 'application/json' }) + stub_request(:get, 'api.example.org/posts').to_return(body: posts_response, headers: { 'Content-Type' => 'application/json' }) + stub_request(:get, 'api.example.org/posts/1').to_return(body: post_response, headers: { 'Content-Type' => 'application/json' }) end def api diff --git a/features/support/fixtures.rb b/features/support/fixtures.rb index eaeada1..20235a9 100644 --- a/features/support/fixtures.rb +++ b/features/support/fixtures.rb @@ -34,7 +34,7 @@ def post_response "comments": [ { "title": "Some comment" - } + } ] } }' diff --git a/hyperclient.gemspec b/hyperclient.gemspec index 15b1e63..b21e880 100644 --- a/hyperclient.gemspec +++ b/hyperclient.gemspec @@ -2,16 +2,16 @@ require File.expand_path('../lib/hyperclient/version', __FILE__) Gem::Specification.new do |gem| - gem.authors = ["Oriol Gual"] - gem.email = ["oriol.gual@gmail.com"] - gem.description = %q{HyperClient is a Ruby Hypermedia API client.} - gem.summary = %q{} - gem.homepage = "http://codegram.github.com/hyperclient/" - gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } + gem.authors = ['Oriol Gual'] + gem.email = ['oriol.gual@gmail.com'] + gem.description = 'HyperClient is a Ruby Hypermedia API client.' + gem.summary = '' + gem.homepage = 'http://codegram.github.com/hyperclient/' + gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) } gem.files = `git ls-files`.split("\n") gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") - gem.name = "hyperclient" - gem.require_paths = ["lib"] + gem.name = 'hyperclient' + gem.require_paths = ['lib'] gem.version = Hyperclient::VERSION gem.add_dependency 'faraday', '~> 0.8' @@ -26,4 +26,5 @@ Gem::Specification.new do |gem| gem.add_development_dependency 'mocha', '~> 0.13' gem.add_development_dependency 'rack-test', '~> 0.6' gem.add_development_dependency 'spinach' + gem.add_development_dependency 'faraday-digestauth' end diff --git a/lib/faraday/connection.rb b/lib/faraday/connection.rb index 801207a..110354c 100644 --- a/lib/faraday/connection.rb +++ b/lib/faraday/connection.rb @@ -1,5 +1,5 @@ require 'faraday' -require_relative 'request/digest_authentication' +require 'faraday/digestauth' module Faraday # Reopen Faraday::Connection to add a helper to set the digest auth data. @@ -11,7 +11,7 @@ class Connection # password - A String with the password. # def digest_auth(user, password) - self.builder.insert(0, Faraday::Request::DigestAuth, user, password) + builder.insert(0, Faraday::Request::DigestAuth, user, password) end end end diff --git a/lib/faraday/request/digest_authentication.rb b/lib/faraday/request/digest_authentication.rb deleted file mode 100644 index ad906fa..0000000 --- a/lib/faraday/request/digest_authentication.rb +++ /dev/null @@ -1,85 +0,0 @@ -require 'faraday' -require 'net/http/digest_auth' - -module Faraday - # Public: A Faraday middleware to use digest authentication. Since order of - # middlewares do care, it should be the first one of the Request middlewares - # in order to work properly (due to how digest authentication works). - # - # If some requests using the connection don't need to use digest auth you - # don't have to worry, the middleware will do nothing. - # - # It uses Net::HTTP::DigestAuth to generate the authorization header but it - # should work with any adapter. - # - # Examples: - # - # connection = Faraday.new(...) do |connection| - # connection.request :digest, USER, PASSWORD - # end - # - # # You can also use it later with a connection: - # connection.digest_auth('USER', 'PASSWORD') - # - class Request::DigestAuth < Faraday::Middleware - - # Public: Initializes a DigestAuth. - # - # app - The Faraday app. - # user - A String with the user to authentication the connection. - # password - A String with the password to authentication the connection. - def initialize(app, user, password) - super(app) - @user, @password = user, password - end - - # Public: Sends a first request with an empty body to get the - # authentication headers and then send the same request with the body and - # authorization header. - # - # env - A Hash with the request environment. - # - # Returns a Faraday::Response. - def call(env) - response = handshake(env) - return response unless response.status == 401 - - env[:request_headers]['Authorization'] = header(response) - @app.call(env) - end - - private - # Internal: Sends the the request with an empry body. - # - # env - A Hash with the request environment. - # - # Returns a Faraday::Response. - def handshake(env) - env_without_body = env.dup - env_without_body.delete(:body) - - @app.call(env_without_body) - end - - # Internal: Builds the authorization header with the authentication data. - # - # response - A Faraday::Response with the authenticate headers. - # - # Returns a String with the DigestAuth header. - def header(response) - uri = response.env[:url] - uri.user = @user - uri.password = @password - - realm = response.headers['www-authenticate'] - method = response.env[:method].to_s.upcase - - Net::HTTP::DigestAuth.new.auth_header(uri, realm, method) - end - end -end - -# Register the middleware as a Request middleware with the name :digest -registry = [Faraday, Faraday::Middleware].find{|mod| mod.respond_to?(:register_middleware)} -raise "Could not find method register_middleware on Faraday or Faraday::Middleware" unless registry -registry.register_middleware :request, digest: Faraday::Request::DigestAuth diff --git a/lib/hyperclient.rb b/lib/hyperclient.rb index 737d66f..85a0096 100644 --- a/lib/hyperclient.rb +++ b/lib/hyperclient.rb @@ -1,5 +1,5 @@ require 'hyperclient/entry_point' -require "hyperclient/version" +require 'hyperclient/version' # Public: Hyperclient namespace. # diff --git a/lib/hyperclient/attributes.rb b/lib/hyperclient/attributes.rb index c57bc38..446670c 100644 --- a/lib/hyperclient/attributes.rb +++ b/lib/hyperclient/attributes.rb @@ -17,7 +17,7 @@ class Attributes < Collection # def initialize(representation) @collection = if representation.is_a?(Hash) - representation.delete_if {|key, value| RESERVED_PROPERTIES.any? {|p| p.match(key) } } + representation.delete_if { |key, _value| RESERVED_PROPERTIES.any? { |p| p.match(key) } } else representation end diff --git a/lib/hyperclient/collection.rb b/lib/hyperclient/collection.rb index c72d8ca..c0873ab 100644 --- a/lib/hyperclient/collection.rb +++ b/lib/hyperclient/collection.rb @@ -69,15 +69,15 @@ def to_s # `collection['name']` # # Returns an Object. - def method_missing(method_name, *args, &block) + def method_missing(method_name, *_args, &_block) @collection.fetch(method_name.to_s) do - raise "Could not find `#{method_name.to_s}` in #{self.class.name}" + fail "Could not find `#{method_name}` in #{self.class.name}" end end # Internal: Accessory method to allow the collection respond to the # methods that will hit method_missing. - def respond_to_missing?(method_name, include_private = false) + def respond_to_missing?(method_name, _include_private = false) @collection.include?(method_name.to_s) end end diff --git a/lib/hyperclient/entry_point.rb b/lib/hyperclient/entry_point.rb index 79bf00f..ef25191 100644 --- a/lib/hyperclient/entry_point.rb +++ b/lib/hyperclient/entry_point.rb @@ -19,7 +19,7 @@ class EntryPoint < Link # # url - A String with the entry point of your API. def initialize(url) - @link = {'href' => url} + @link = { 'href' => url } @entry_point = self end @@ -27,10 +27,11 @@ def initialize(url) # # Returns a Faraday::Connection. def connection - @connection ||= Faraday.new(url, {headers: default_headers}, &default_faraday_block) + @connection ||= Faraday.new(url, { headers: default_headers }, &default_faraday_block) end private + # Internal: Returns a block to initialize the Faraday connection. The # default block includes a middleware to encode requests as JSON, a # response middleware to parse JSON responses and sets the adapter as @@ -43,7 +44,7 @@ def connection def default_faraday_block lambda do |faraday| faraday.use FaradayMiddleware::FollowRedirects - faraday.request :json + faraday.request :json faraday.response :json, content_type: /\bjson$/ faraday.adapter :net_http end @@ -54,7 +55,7 @@ def default_faraday_block # # Returns a Hash. def default_headers - {'Content-Type' => 'application/json', 'Accept' => 'application/json'} + { 'Content-Type' => 'application/json', 'Accept' => 'application/json' } end end end diff --git a/lib/hyperclient/link.rb b/lib/hyperclient/link.rb index d07a6e3..097dbad 100644 --- a/lib/hyperclient/link.rb +++ b/lib/hyperclient/link.rb @@ -41,7 +41,7 @@ def expand(uri_variables) # no uri variables to expand it. def url return @link['href'] unless templated? - raise MissingURITemplateVariablesException if @uri_variables == nil + fail MissingURITemplateVariablesException if @uri_variables.nil? @url ||= uri_template.expand(@uri_variables) end @@ -101,45 +101,45 @@ def connection end def get - Futuroscope::Future.new{ + Futuroscope::Future.new do connection.get(url) - } + end end def options - Futuroscope::Future.new{ + Futuroscope::Future.new do connection.run_request(:options, url, nil, nil) - } + end end def head - Futuroscope::Future.new{ + Futuroscope::Future.new do connection.head(url) - } + end end def delete - Futuroscope::Future.new{ + Futuroscope::Future.new do connection.delete(url) - } + end end def post(params = {}) - Futuroscope::Future.new{ + Futuroscope::Future.new do connection.post(url, params) - } + end end def put(params = {}) - Futuroscope::Future.new{ + Futuroscope::Future.new do connection.put(url, params) - } + end end def patch(params = {}) - Futuroscope::Future.new{ + Futuroscope::Future.new do connection.patch(url, params) - } + end end def inspect @@ -147,6 +147,7 @@ def inspect end private + # Internal: Delegate the method to the API if it exists. # # This allows `api.links.posts.embedded` instead of @@ -161,7 +162,7 @@ def method_missing(method, *args, &block) # Internal: Accessory method to allow the link respond to the # methods that will hit method_missing. - def respond_to_missing?(method, include_private = false) + def respond_to_missing?(method, _include_private = false) resource.respond_to?(method.to_s) end @@ -182,10 +183,9 @@ def uri_template # Public: Exception that is raised when building a templated Link without uri # variables. class MissingURITemplateVariablesException < StandardError - # Public: Returns a String with the exception message. def message - "The URL to this links is templated, but no variables where given." + 'The URL to this links is templated, but no variables where given.' end end end diff --git a/lib/hyperclient/link_collection.rb b/lib/hyperclient/link_collection.rb index 24f3896..768f474 100644 --- a/lib/hyperclient/link_collection.rb +++ b/lib/hyperclient/link_collection.rb @@ -15,14 +15,15 @@ class LinkCollection < Collection # collection - The Hash with the links. # entry_point - The EntryPoint object to inject the configuration. def initialize(collection, entry_point) - raise "Invalid response for LinkCollection. The response was: #{collection.inspect}" if collection && !collection.respond_to?(:collect) + fail "Invalid response for LinkCollection. The response was: #{collection.inspect}" if collection && !collection.respond_to?(:collect) - @collection = (collection || {}).inject({}) do |hash, (name, link)| + @collection = (collection || {}).reduce({}) do |hash, (name, link)| hash.update(name => build_link(link, entry_point)) end end private + # Internal: Creates links from the response hash. # # link_or_links - A Hash or an Array of hashes with the links to build. @@ -33,7 +34,7 @@ def build_link(link_or_links, entry_point) return unless link_or_links return Link.new(link_or_links, entry_point) unless link_or_links.respond_to?(:to_ary) - link_or_links.collect do |link| + link_or_links.map do |link| build_link(link, entry_point) end end diff --git a/lib/hyperclient/resource.rb b/lib/hyperclient/resource.rb index e005578..f07fbb1 100644 --- a/lib/hyperclient/resource.rb +++ b/lib/hyperclient/resource.rb @@ -31,7 +31,7 @@ class Resource # # representation - The hash with the HAL representation of the Resource. # entry_point - The EntryPoint object to inject the configutation. - def initialize(representation, entry_point, response=nil) + def initialize(representation, entry_point, response = nil) representation = representation ? representation.dup : {} @links = LinkCollection.new(representation['_links'], entry_point) @embedded = ResourceCollection.new(representation['_embedded'], entry_point) @@ -53,6 +53,7 @@ def status end private + # Internal: Returns the self Link of the Resource. Used to handle the HTTP # methods. def self_link diff --git a/lib/hyperclient/resource_collection.rb b/lib/hyperclient/resource_collection.rb index 0790ada..f93d2b8 100644 --- a/lib/hyperclient/resource_collection.rb +++ b/lib/hyperclient/resource_collection.rb @@ -18,12 +18,13 @@ class ResourceCollection < Collection # def initialize(collection, entry_point) @entry_point = entry_point - @collection = (collection || {}).inject({}) do |hash, (name, resource)| + @collection = (collection || {}).reduce({}) do |hash, (name, resource)| hash.update(name => build_resource(resource)) end end private + def build_resource(representation) return representation.map(&method(:build_resource)) if representation.is_a?(Array) diff --git a/test/faraday/digest_authentication_test.rb b/test/faraday/digest_authentication_test.rb deleted file mode 100644 index 3affa33..0000000 --- a/test/faraday/digest_authentication_test.rb +++ /dev/null @@ -1,41 +0,0 @@ -require_relative '../test_helper' -require 'faraday/request/digest_authentication' - -module Faraday - describe Request::DigestAuth do - let(:connection) do - Faraday.new('http://api.example.org/') do |builder| - builder.request :digest, 'USER', 'PASS' - builder.adapter :net_http - end - end - - describe 'when the server does not return a 401' do - it 'does nothing' do - stub_request(:get, 'http://api.example.org/productions/1'). - to_return(status: 500, body: 'Foo body') - - response = connection.get('/productions/1') - response.body.must_equal 'Foo body' - end - end - - describe 'when the server returns a 401' do - let(:first_call_headers) { 'Digest realm="MyApp", algorithm=MD5' } - let(:second_call_headers) { 'Digest username="USER", realm="MyApp", uri="/", algorithm="MD5"' } - it 'authenticates using digest' do - stub_request(:get, 'http://api.example.org/productions/1'). - with(body: nil). - to_return(status: 401, headers: {'www-authenticate' => first_call_headers}) - - stub_request(:get, 'http://api.example.org/productions/1'). - with(body: "{\"foo\":1}", - headers: {'Authorization' => %r{second_call_headers}}). - to_return(body: '{"resource": "This is the resource"}', - headers: {content_type: 'application/json'}) - - connection.get('/productions/1') - end - end - end -end diff --git a/test/hyperclient/attributes_test.rb b/test/hyperclient/attributes_test.rb index 731103e..05ee3b3 100644 --- a/test/hyperclient/attributes_test.rb +++ b/test/hyperclient/attributes_test.rb @@ -4,7 +4,7 @@ module Hyperclient describe Attributes do let(:representation) do - JSON.parse( File.read('test/fixtures/element.json')) + JSON.parse(File.read('test/fixtures/element.json')) end let(:attributes) do @@ -24,7 +24,7 @@ module Hyperclient attributes.permitted.must_equal true attributes.must_respond_to :title - attributes.title.must_equal "Real World ASP.NET MVC3" + attributes.title.must_equal 'Real World ASP.NET MVC3' end # Underscores should be allowed per http://tools.ietf.org/html/draft-kelly-json-hal#appendix-B.4 diff --git a/test/hyperclient/collection_test.rb b/test/hyperclient/collection_test.rb index a2be763..4d66fb4 100644 --- a/test/hyperclient/collection_test.rb +++ b/test/hyperclient/collection_test.rb @@ -4,7 +4,7 @@ module Hyperclient describe Collection do let(:representation) do - JSON.parse( File.read('test/fixtures/element.json')) + JSON.parse(File.read('test/fixtures/element.json')) end let(:collection) do @@ -28,11 +28,11 @@ module Hyperclient end it 'acts as enumerable' do - names = collection.map do |name, value| + names = collection.map do |name, _value| name end - names.must_equal ['_links', 'title', 'description', 'permitted', '_hidden_attribute', '_embedded'] + names.must_equal %w(_links title description permitted _hidden_attribute _embedded) end describe '#to_hash' do @@ -53,16 +53,16 @@ module Hyperclient describe '#fetch' do it 'returns the value for keys that exist' do - collection.fetch('title').must_equal "Real World ASP.NET MVC3" + collection.fetch('title').must_equal 'Real World ASP.NET MVC3' end it 'raises an error for missing keys' do - Proc.new { collection.fetch('missing key') }.must_raise KeyError + proc { collection.fetch('missing key') }.must_raise KeyError end describe 'with a default value' do it 'returns the value for keys that exist' do - collection.fetch('title', 'default').must_equal "Real World ASP.NET MVC3" + collection.fetch('title', 'default').must_equal 'Real World ASP.NET MVC3' end it 'returns the default value for missing keys' do @@ -73,4 +73,3 @@ module Hyperclient end end - diff --git a/test/hyperclient/link_collection_test.rb b/test/hyperclient/link_collection_test.rb index 33d5aef..c24e79f 100644 --- a/test/hyperclient/link_collection_test.rb +++ b/test/hyperclient/link_collection_test.rb @@ -3,10 +3,10 @@ module Hyperclient describe LinkCollection do - let(:entry_point) { stub('Entry point', config: {base_uri: '/'}) } + let(:entry_point) { stub('Entry point', config: { base_uri: '/' }) } let(:representation) do - JSON.parse( File.read('test/fixtures/element.json')) + JSON.parse(File.read('test/fixtures/element.json')) end let(:links) do @@ -30,7 +30,7 @@ module Hyperclient links['gizmos'].must_be_kind_of Array end - describe "array of links" do + describe 'array of links' do let(:gizmos) { links.gizmos } it 'should have 2 items' do @@ -44,7 +44,7 @@ module Hyperclient end end - describe "null link value" do + describe 'null link value' do let(:null_link) { links.null_link } it 'must be nil' do null_link.must_be_nil diff --git a/test/hyperclient/link_test.rb b/test/hyperclient/link_test.rb index c7a5a8a..1ef2c9c 100644 --- a/test/hyperclient/link_test.rb +++ b/test/hyperclient/link_test.rb @@ -10,8 +10,8 @@ module Hyperclient %w(type deprecation name profile title hreflang).each do |prop| describe prop do - it "returns the property value" do - link = Link.new({prop => 'value'}, entry_point) + it 'returns the property value' do + link = Link.new({ prop => 'value' }, entry_point) link.send(prop).must_equal 'value' end @@ -24,7 +24,7 @@ module Hyperclient describe 'templated?' do it 'returns true if the link is templated' do - link = Link.new({'templated' => true}, entry_point) + link = Link.new({ 'templated' => true }, entry_point) link.templated?.must_equal true end @@ -38,13 +38,13 @@ module Hyperclient describe 'variables' do it 'returns a list of required variables' do - link = Link.new({'href' => '/orders{?id,owner}', 'templated' => true}, entry_point) + link = Link.new({ 'href' => '/orders{?id,owner}', 'templated' => true }, entry_point) - link.variables.must_equal ['id', 'owner'] + link.variables.must_equal %w(id owner) end it 'returns an empty array for untemplated links' do - link = Link.new({'href' => '/orders'}, entry_point) + link = Link.new({ 'href' => '/orders' }, entry_point) link.variables.must_equal [] end @@ -52,33 +52,33 @@ module Hyperclient describe 'expand' do it 'buils a Link with the templated URI representation' do - link = Link.new({'href' => '/orders{?id}', 'templated' => true}, entry_point) + link = Link.new({ 'href' => '/orders{?id}', 'templated' => true }, entry_point) - Link.expects(:new).with(anything, entry_point, {id: '1'}) + Link.expects(:new).with(anything, entry_point, id: '1') link.expand(id: '1') end it 'raises if no uri variables are given' do - link = Link.new({'href' => '/orders{?id}', 'templated' => true}, entry_point) + link = Link.new({ 'href' => '/orders{?id}', 'templated' => true }, entry_point) lambda { link.expand }.must_raise ArgumentError end end describe 'url' do it 'raises when missing required uri_variables' do - link = Link.new({'href' => '/orders{?id}', 'templated' => true}, entry_point) + link = Link.new({ 'href' => '/orders{?id}', 'templated' => true }, entry_point) lambda { link.url }.must_raise MissingURITemplateVariablesException end it 'expands an uri template with variables' do - link = Link.new({'href' => '/orders{?id}', 'templated' => true}, entry_point, {id: 1}) + link = Link.new({ 'href' => '/orders{?id}', 'templated' => true }, entry_point, id: 1) link.url.must_equal '/orders?id=1' end it 'returns the link when no uri template' do - link = Link.new({'href' => '/orders'}, entry_point) + link = Link.new({ 'href' => '/orders' }, entry_point) link.url.must_equal '/orders' end end @@ -89,18 +89,18 @@ module Hyperclient Resource.expects(:new).with({}, entry_point, mock_response) - link = Link.new({'href' => '/'}, entry_point) + link = Link.new({ 'href' => '/' }, entry_point) link.expects(:get).returns(mock_response) link.resource end - it "has an empty body when the response fails" do + it 'has an empty body when the response fails' do mock_response = mock(success?: false) Resource.expects(:new).with(nil, entry_point, mock_response) - link = Link.new({'href' => '/'}, entry_point) + link = Link.new({ 'href' => '/' }, entry_point) link.expects(:get).returns(mock_response) link.resource @@ -115,7 +115,7 @@ module Hyperclient describe 'get' do it 'sends a GET request with the link url' do - link = Link.new({'href' => '/productions/1'}, entry_point) + link = Link.new({ 'href' => '/productions/1' }, entry_point) entry_point.connection.expects(:get).with('/productions/1') link.get.inspect @@ -124,7 +124,7 @@ module Hyperclient describe 'options' do it 'sends a OPTIONS request with the link url' do - link = Link.new({'href' => '/productions/1'}, entry_point) + link = Link.new({ 'href' => '/productions/1' }, entry_point) entry_point.connection.expects(:run_request).with(:options, '/productions/1', nil, nil) link.options.inspect @@ -133,7 +133,7 @@ module Hyperclient describe 'head' do it 'sends a HEAD request with the link url' do - link = Link.new({'href' => '/productions/1'}, entry_point) + link = Link.new({ 'href' => '/productions/1' }, entry_point) entry_point.connection.expects(:head).with('/productions/1') link.head.inspect @@ -142,7 +142,7 @@ module Hyperclient describe 'delete' do it 'sends a DELETE request with the link url' do - link = Link.new({'href' => '/productions/1'}, entry_point) + link = Link.new({ 'href' => '/productions/1' }, entry_point) entry_point.connection.expects(:delete).with('/productions/1') link.delete.inspect @@ -150,11 +150,11 @@ module Hyperclient end describe 'post' do - let(:link) { Link.new({'href' => '/productions/1'}, entry_point) } + let(:link) { Link.new({ 'href' => '/productions/1' }, entry_point) } it 'sends a POST request with the link url and params' do - entry_point.connection.expects(:post).with('/productions/1', {'foo' => 'bar'}) - link.post({'foo' => 'bar'}).inspect + entry_point.connection.expects(:post).with('/productions/1', 'foo' => 'bar') + link.post('foo' => 'bar').inspect end it 'defaults params to an empty hash' do @@ -164,11 +164,11 @@ module Hyperclient end describe 'put' do - let(:link) { Link.new({'href' => '/productions/1'}, entry_point) } + let(:link) { Link.new({ 'href' => '/productions/1' }, entry_point) } it 'sends a PUT request with the link url and params' do - entry_point.connection.expects(:put).with('/productions/1', {'foo' => 'bar'}) - link.put({'foo' => 'bar'}).inspect + entry_point.connection.expects(:put).with('/productions/1', 'foo' => 'bar') + link.put('foo' => 'bar').inspect end it 'defaults params to an empty hash' do @@ -178,11 +178,11 @@ module Hyperclient end describe 'patch' do - let(:link) { Link.new({'href' => '/productions/1'}, entry_point) } + let(:link) { Link.new({ 'href' => '/productions/1' }, entry_point) } it 'sends a PATCH request with the link url and params' do - entry_point.connection.expects(:patch).with('/productions/1', {'foo' => 'bar'}) - link.patch({'foo' => 'bar'}).inspect + entry_point.connection.expects(:patch).with('/productions/1', 'foo' => 'bar') + link.patch('foo' => 'bar').inspect end it 'defaults params to an empty hash' do @@ -193,7 +193,7 @@ module Hyperclient describe 'inspect' do it 'outputs a custom-friendly output' do - link = Link.new({'href'=>'/productions/1'}, 'foo') + link = Link.new({ 'href' => '/productions/1' }, 'foo') link.inspect.must_include 'Link' link.inspect.must_include '"href"=>"/productions/1"' @@ -202,12 +202,12 @@ module Hyperclient describe 'method_missing' do before do - stub_request(:get, "http://myapi.org/orders"). - to_return(body: '{"resource": "This is the resource"}') + stub_request(:get, 'http://myapi.org/orders') + .to_return(body: '{"resource": "This is the resource"}') Resource.stubs(:new).returns(resource) end - let(:link) { Link.new({'href' => 'http://myapi.org/orders'}, entry_point) } + let(:link) { Link.new({ 'href' => 'http://myapi.org/orders' }, entry_point) } let(:resource) { mock('Resource') } it 'delegates unkown methods to the resource' do diff --git a/test/hyperclient/resource_collection_test.rb b/test/hyperclient/resource_collection_test.rb index e46ad71..adb5750 100644 --- a/test/hyperclient/resource_collection_test.rb +++ b/test/hyperclient/resource_collection_test.rb @@ -3,10 +3,10 @@ module Hyperclient describe ResourceCollection do - let(:entry_point) { stub('Entry point', config: {base_uri: '/'}) } + let(:entry_point) { stub('Entry point', config: { base_uri: '/' }) } let(:representation) do - JSON.parse( File.read('test/fixtures/element.json')) + JSON.parse(File.read('test/fixtures/element.json')) end let(:resources) do diff --git a/test/hyperclient/resource_test.rb b/test/hyperclient/resource_test.rb index 8ff8c2e..f83e2d5 100644 --- a/test/hyperclient/resource_test.rb +++ b/test/hyperclient/resource_test.rb @@ -7,24 +7,24 @@ module Hyperclient describe 'initialize' do it 'initializes its links' do - LinkCollection.expects(:new).with({"self" => { "href" => "/orders/523" }}, entry_point) + LinkCollection.expects(:new).with({ 'self' => { 'href' => '/orders/523' } }, entry_point) - Resource.new({'_links' => {"self" => { "href" => "/orders/523" } }}, entry_point) + Resource.new({ '_links' => { 'self' => { 'href' => '/orders/523' } } }, entry_point) end it 'initializes its attributes' do - Attributes.expects(:new).with({foo: :bar}) + Attributes.expects(:new).with(foo: :bar) - Resource.new({foo: :bar}, entry_point) + Resource.new({ foo: :bar }, entry_point) end it 'initializes links' do - ResourceCollection.expects(:new).with({"orders" => []}, entry_point) + ResourceCollection.expects(:new).with({ 'orders' => [] }, entry_point) - Resource.new({'_embedded' => {"orders" => [] }}, entry_point) + Resource.new({ '_embedded' => { 'orders' => [] } }, entry_point) end - it "initializes the response" do + it 'initializes the response' do mock_response = mock(body: {}) resource = Resource.new(mock_response.body, entry_point, mock_response) @@ -32,7 +32,7 @@ module Hyperclient resource.response.must_equal mock_response end - it "does not mutate the response.body" do + it 'does not mutate the response.body' do body = { 'foo' => 'bar', '_links' => {}, '_embedded' => {} } mock_response = stub(body: body.dup) @@ -71,14 +71,14 @@ module Hyperclient self_link = mock('Self Link') self_link.expects(:get) - LinkCollection.expects(:new).returns({'self' => self_link}) + LinkCollection.expects(:new).returns('self' => self_link) resource = Resource.new({}, entry_point) resource.get end - describe ".success?" do - describe "with a response object" do + describe '.success?' do + describe 'with a response object' do let(:resource) do Resource.new({}, entry_point, mock_response) end @@ -87,24 +87,24 @@ module Hyperclient mock(success?: true) end - it "proxies to the response object" do + it 'proxies to the response object' do resource.success?.must_equal true end end - describe "without a response object" do + describe 'without a response object' do let(:resource) do Resource.new({}, entry_point) end - it "returns nil" do + it 'returns nil' do resource.success?.must_be_nil end end end - describe ".status" do - describe "with a response object" do + describe '.status' do + describe 'with a response object' do let(:resource) do Resource.new({}, entry_point, mock_response) end @@ -113,17 +113,17 @@ module Hyperclient mock(status: 200) end - it "proxies to the response object" do + it 'proxies to the response object' do resource.status.must_equal 200 end end - describe "without a response object" do + describe 'without a response object' do let(:resource) do Resource.new({}, entry_point) end - it "returns nil" do + it 'returns nil' do resource.status.must_be_nil end end diff --git a/test/test_helper.rb b/test/test_helper.rb index bb37b7e..e776ef9 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,4 +1,4 @@ -$: << 'lib' +$LOAD_PATH << 'lib' gem 'minitest' require 'minitest/spec' @@ -7,4 +7,4 @@ require 'turn' require 'webmock/minitest' require 'json' -require 'pry' \ No newline at end of file +require 'pry'