hyperclient 0.9.1 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 494b4be638b3b6d76edd4d07e5b12e36433dfd84c9a756dec34a278fd9ea2faa
4
- data.tar.gz: 1d9e97e2a76cdf4a991a5803bd14eadf40ae300e4065cbacdedee64b66f19a3c
3
+ metadata.gz: 5f55cb82362d8eca25347e15c91387bbf2957f1f1241af27fccff1086b412d1b
4
+ data.tar.gz: f31325a293b0aec888b94910b8c3dc28d2f30a6666fe59063b4112251f46e7c4
5
5
  SHA512:
6
- metadata.gz: bd401bb429c28fb75af0c95908deaa43f91a67923c47ba17ba369eb238252add1657ea1aa2b57f9721c59113c06d394274268ade288618314b93c7d4e0c11b31
7
- data.tar.gz: 5892d3cabd8bad2e6bd5c6e9a5c6ef7f3fa9f7376c6aa39e9225acf8c37160da3550b66ff420440a9565d29ea898784bd3093bd36b09cbf1302f45aaa7d0a5a6
6
+ metadata.gz: e9b17e112614d3c600497c6c7cfd56268195427da789629d006742ff96e70d2b6972ba16fbfa075ab62613eeace923d8fdb4f231b9d86a04f82b75fa5d4a4826
7
+ data.tar.gz: 8a8861e266967702c86d5762ec5b786687298c37e797a5c324583c9d3c9d2fe4dc83cf8841c912db3d14a0bf731d1dbee0c1c85b3d43961589c5741b43b3f128
data/.rubocop.yml CHANGED
@@ -3,8 +3,8 @@ inherit_from: .rubocop_todo.yml
3
3
  AllCops:
4
4
  TargetRubyVersion: 2.3
5
5
 
6
- Metrics/BlockLength:
7
- ExcludedMethods: [it, describe]
6
+ Metrics:
7
+ Enabled: false
8
8
 
9
9
  Style/FrozenStringLiteralComment:
10
- Enabled: false
10
+ Enabled: false
data/.rubocop_todo.yml CHANGED
@@ -1,26 +1,11 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2019-08-25 11:12:51 -0400 using RuboCop version 0.74.0.
3
+ # on 2020-12-03 14:08:14 -0500 using RuboCop version 0.81.0.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
- # Offense count: 1
10
- # Configuration parameters: CountComments.
11
- Metrics/ClassLength:
12
- Max: 103
13
-
14
- # Offense count: 3
15
- # Configuration parameters: CountComments, ExcludedMethods.
16
- Metrics/MethodLength:
17
- Max: 25
18
-
19
- # Offense count: 3
20
- # Configuration parameters: CountComments.
21
- Metrics/ModuleLength:
22
- Max: 265
23
-
24
9
  # Offense count: 2
25
10
  # Cop supports --auto-correct.
26
11
  # Configuration parameters: AutoCorrect, EnforcedStyle.
@@ -46,14 +31,22 @@ Style/DoubleNegation:
46
31
  - 'lib/hyperclient/curie.rb'
47
32
  - 'lib/hyperclient/link.rb'
48
33
 
34
+ # Offense count: 3
35
+ # Cop supports --auto-correct.
36
+ Style/IfUnlessModifier:
37
+ Exclude:
38
+ - 'lib/hyperclient/link_collection.rb'
39
+ - 'lib/hyperclient/resource.rb'
40
+ - 'lib/hyperclient/resource_collection.rb'
41
+
49
42
  # Offense count: 1
50
43
  Style/MethodMissingSuper:
51
44
  Exclude:
52
45
  - 'lib/hyperclient/collection.rb'
53
46
 
54
- # Offense count: 93
47
+ # Offense count: 101
55
48
  # Cop supports --auto-correct.
56
49
  # Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
57
50
  # URISchemes: http, https
58
- Metrics/LineLength:
59
- Max: 142
51
+ Layout/LineLength:
52
+ Max: 147
data/.travis.yml CHANGED
@@ -4,22 +4,21 @@ sudo: false
4
4
 
5
5
  matrix:
6
6
  include:
7
- - rvm: 2.6.3
8
- - rvm: 2.5.5
9
- - rvm: 2.4.6
10
- - rvm: 2.4.6
7
+ - rvm: 2.6.6
8
+ env: FARADAY_VERSION=0.9.0
9
+ - rvm: 2.6.6
10
+ env: FARADAY_VERSION=0.17.0
11
+ - rvm: 2.6.6
12
+ env: FARADAY_VERSION="~> 1.0"
13
+ - rvm: 2.6.6
11
14
  script:
12
15
  - bundle exec danger
16
+ - rvm: 2.3.8
13
17
  - rvm: jruby-9.2.7.0
14
18
  - rvm: jruby-head
15
- - rvm: 2.3.8
16
19
  - rvm: ruby-head
17
20
  allow_failures:
18
21
  - rvm: ruby-head
19
22
  - rvm: jruby-head
20
23
 
21
- before_install:
22
- - gem update --system
23
- - gem install bundler
24
-
25
24
  bundler_args: --without development
data/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  ## Changelog
2
2
 
3
+ ### 1.0.1 (2021/01/02)
4
+
5
+ * [#193](https://github.com/codegram/hyperclient/pull/193): Auto-paginate collections - [@dblock](https://github.com/dblock).
6
+ * [#163](https://github.com/codegram/hyperclient/pull/163): Test against Faraday 0.9, 0.17 and 1.0+ - [@dblock](https://github.com/dblock).
7
+ * [#199](https://github.com/codegram/hyperclient/pull/199): Use digest_auth from faraday-digestauth - [@dblock](https://github.com/dblock).
8
+
9
+ ### 1.0.0 (2021/01/02)
10
+
11
+ * NOTE: **⚠ This version has been yanked ⚠** - [@dblock](https://github.com/dblock).
12
+
13
+ ### 0.9.3 (2020/05/14)
14
+
15
+ * [#149](https://github.com/codegram/hyperclient/pull/149): Address Faraday warnings - [@yuki24](https://github.com/yuki24).
16
+ * [#160](https://github.com/codegram/hyperclient/pull/160): Require newer 'faraday-digestauth' - [@dblock](https://github.com/dblock).
17
+
18
+ ### 0.9.2 (2020/05/12)
19
+
20
+ * NOTE: **⚠ This version has been yanked ⚠** - [@dblock](https://github.com/dblock).
21
+
3
22
  ### 0.9.1 (2019/08/25)
4
23
 
5
24
  * NOTE: **⚠ This version is no longer tested with Ruby < 2.3 ⚠** - [@ivoanjo](https://github.com/ivoanjo).
data/Gemfile CHANGED
@@ -3,6 +3,8 @@ git_source(:github) { |repo| "https://github.com/#{repo['/'] ? repo : "#{repo}/#
3
3
 
4
4
  source 'https://rubygems.org'
5
5
 
6
+ gem 'faraday', ENV['FARADAY_VERSION'] if ENV.key?('FARADAY_VERSION')
7
+
6
8
  gemspec
7
9
 
8
10
  group :development do
@@ -16,7 +18,7 @@ end
16
18
 
17
19
  group :development, :test do
18
20
  gem 'rake'
19
- gem 'rubocop', '~> 0.74.0', require: false
21
+ gem 'rubocop', '0.81.0', require: false
20
22
  gem 'simplecov', require: false
21
23
  end
22
24
 
data/README.md CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  [![Gem Version](http://img.shields.io/gem/v/hyperclient.svg)](http://badge.fury.io/rb/hyperclient)
4
4
  [![Build Status](http://img.shields.io/travis/codegram/hyperclient.svg)](https://travis-ci.org/codegram/hyperclient)
5
- [![Dependency Status](https://gemnasium.com/codegram/hyperclient.svg)](https://gemnasium.com/codegram/hyperclient)
6
5
  [![Code Climate](https://codeclimate.com/github/codegram/hyperclient.svg)](https://codeclimate.com/github/codegram/hyperclient)
7
6
  [![Coverage Status](https://img.shields.io/coveralls/codegram/hyperclient.svg)](https://coveralls.io/r/codegram/hyperclient?branch=master)
8
7
 
@@ -86,12 +85,19 @@ api = Hyperclient.new('https://grape-with-roar.herokuapp.com/api') do |client|
86
85
  end
87
86
  ```
88
87
 
89
- You can modify headers or specify authentication after a connection has been created. Hyperclient supports Basic, Token or Digest auth as well as many other Faraday extensions.
88
+ You can modify headers or specify authentication after a connection has been created. Hyperclient supports Basic, Token or [Digest auth](https://github.com/bhaberer/faraday-digestauth) as well as many other Faraday extensions.
90
89
 
91
90
  ```ruby
92
- api = Hyperclient.new('https://grape-with-roar.herokuapp.com/api')
93
- api.digest_auth('username', 'password')
94
- api.headers.update('Accept-Encoding' => 'deflate, gzip')
91
+ require 'faraday/digestauth'
92
+
93
+ api = Hyperclient.new('https://grape-with-roar.herokuapp.com/api') do |client|
94
+ client.connection(default: false) do |conn|
95
+ conn.request :digest, 'username', 'password'
96
+ conn.request :json
97
+ conn.response :json, content_type: /\bjson$/
98
+ conn.adapter :net_http
99
+ end
100
+ end
95
101
  ```
96
102
 
97
103
  You can access the Faraday connection directly after it has been created and add middleware to it. As an example, you could use the [faraday-http-cache-middleware](https://github.com/plataformatec/faraday-http-cache).
@@ -103,7 +109,7 @@ api.connection.use :http_cache
103
109
 
104
110
  ## Resources and Attributes
105
111
 
106
- Hyperclient will fetch and discover the resources from your API.
112
+ Hyperclient will fetch and discover the resources from your API and automatically paginate when possible.
107
113
 
108
114
  ```ruby
109
115
  api.splines.each do |spline|
@@ -7,6 +7,11 @@ Feature: API navigation
7
7
  When I connect to the API
8
8
  Then I should be able to navigate to posts and authors
9
9
 
10
+ Scenario: Links
11
+ When I connect to the API
12
+ Then I should be able to paginate posts
13
+ Then I should be able to paginate authors
14
+
10
15
  Scenario: Templated links
11
16
  Given I connect to the API
12
17
  When I search for a post with a templated link
@@ -9,6 +9,19 @@ class Spinach::Features::ApiNavigation < Spinach::FeatureSteps
9
9
  assert_requested :get, 'http://api.example.org/authors'
10
10
  end
11
11
 
12
+ step 'I should be able to paginate posts' do
13
+ assert_kind_of Enumerator, api.posts.each
14
+ assert_equal 4, api.posts.to_a.count
15
+ assert_requested :get, 'http://api.example.org/posts'
16
+ assert_requested :get, 'http://api.example.org/posts?page=2'
17
+ assert_requested :get, 'http://api.example.org/posts?page=3'
18
+ end
19
+
20
+ step 'I should be able to paginate authors' do
21
+ assert_equal 1, api._links['api:authors'].to_a.count
22
+ assert_requested :get, 'http://api.example.org/authors'
23
+ end
24
+
12
25
  step 'I search for a post with a templated link' do
13
26
  api._links.search._expand(q: 'something')._resource
14
27
  end
@@ -50,8 +63,8 @@ class Spinach::Features::ApiNavigation < Spinach::FeatureSteps
50
63
  step 'I should be able to count embedded items' do
51
64
  assert_equal 2, api._links.posts._resource._embedded.posts.count
52
65
  assert_equal 2, api.posts._embedded.posts.count
53
- assert_equal 2, api.posts.count
54
- assert_equal 2, api.posts.map.count
66
+ assert_equal 4, api.posts.count
67
+ assert_equal 4, api.posts.map.count
55
68
  end
56
69
 
57
70
  step 'I should be able to iterate over embedded items' do
@@ -59,6 +72,6 @@ class Spinach::Features::ApiNavigation < Spinach::FeatureSteps
59
72
  api.posts.each do |_post|
60
73
  count += 1
61
74
  end
62
- assert_equal 2, count
75
+ assert_equal 4, count
63
76
  end
64
77
  end
@@ -25,7 +25,7 @@ class Spinach::Features::DefaultConfig < Spinach::FeatureSteps
25
25
  end
26
26
 
27
27
  step 'it should have been parsed as JSON' do
28
- @posts._attributes.total_posts.to_i.must_equal 2
29
- @posts._attributes['total_posts'].to_i.must_equal 2
28
+ @posts._attributes.total_posts.to_i.must_equal 4
29
+ @posts._attributes['total_posts'].to_i.must_equal 4
30
30
  end
31
31
  end
@@ -8,8 +8,14 @@ module API
8
8
  WebMock::Config.instance.query_values_notation = :flat_array
9
9
 
10
10
  stub_request(:any, /api.example.org*/).to_return(body: root_response, headers: { 'Content-Type' => 'application/hal+json' })
11
+ stub_request(:get, 'api.example.org').to_return(body: root_response, headers: { 'Content-Type' => 'application/hal+json' })
12
+ stub_request(:get, 'api.example.org/authors').to_return(body: authors_response, headers: { 'Content-Type' => 'application/hal+json' })
11
13
  stub_request(:get, 'api.example.org/posts').to_return(body: posts_response, headers: { 'Content-Type' => 'application/hal+json' })
12
- stub_request(:get, 'api.example.org/posts/1').to_return(body: post_response, headers: { 'Content-Type' => 'application/hal+json' })
14
+ stub_request(:get, 'api.example.org/posts?page=2').to_return(body: posts_page2_response, headers: { 'Content-Type' => 'application/hal+json' })
15
+ stub_request(:get, 'api.example.org/posts?page=3').to_return(body: posts_page3_response, headers: { 'Content-Type' => 'application/hal+json' })
16
+ stub_request(:get, 'api.example.org/posts/1').to_return(body: post1_response, headers: { 'Content-Type' => 'application/hal+json' })
17
+ stub_request(:get, 'api.example.org/posts/2').to_return(body: post2_response, headers: { 'Content-Type' => 'application/hal+json' })
18
+ stub_request(:get, 'api.example.org/posts/3').to_return(body: post3_response, headers: { 'Content-Type' => 'application/hal+json' })
13
19
  stub_request(:get, 'api.example.org/page2').to_return(body: page2_response, headers: { 'Content-Type' => 'application/hal+json' })
14
20
  stub_request(:get, 'api.example.org/page3').to_return(body: page3_response, headers: { 'Content-Type' => 'application/hal+json' })
15
21
  end
@@ -15,13 +15,32 @@ module Spinach
15
15
  }'
16
16
  end
17
17
 
18
+ def authors_response
19
+ '{
20
+ "_links": {
21
+ "self": { "href": "/authors" }
22
+ },
23
+ "_embedded": {
24
+ "api:authors": [
25
+ {
26
+ "name": "Lorem Ipsum",
27
+ "_links": {
28
+ "self": { "href": "/authors/1" }
29
+ }
30
+ }
31
+ ]
32
+ }
33
+ }'
34
+ end
35
+
18
36
  def posts_response
19
37
  '{
20
38
  "_links": {
21
39
  "self": { "href": "/posts" },
40
+ "next": {"href": "/posts?page=2"},
22
41
  "last_post": {"href": "/posts/1"}
23
42
  },
24
- "total_posts": "2",
43
+ "total_posts": "4",
25
44
  "_embedded": {
26
45
  "posts": [
27
46
  {
@@ -43,7 +62,48 @@ module Spinach
43
62
  }'
44
63
  end
45
64
 
46
- def post_response
65
+ def posts_page2_response
66
+ '{
67
+ "_links": {
68
+ "self": { "href": "/posts?page=2" },
69
+ "next": { "href": "/posts?page=3" }
70
+ },
71
+ "total_posts": "4",
72
+ "_embedded": {
73
+ "posts": [
74
+ {
75
+ "title": "My third blog post",
76
+ "body": "Lorem ipsum dolor sit amet",
77
+ "_links": {
78
+ "self": { "href": "/posts/3" }
79
+ }
80
+ }
81
+ ]
82
+ }
83
+ }'
84
+ end
85
+
86
+ def posts_page3_response
87
+ '{
88
+ "_links": {
89
+ "self": { "href": "/posts?page=3" }
90
+ },
91
+ "total_posts": "4",
92
+ "_embedded": {
93
+ "posts": [
94
+ {
95
+ "title": "My third blog post",
96
+ "body": "Lorem ipsum dolor sit amet",
97
+ "_links": {
98
+ "self": { "href": "/posts/4" }
99
+ }
100
+ }
101
+ ]
102
+ }
103
+ }'
104
+ end
105
+
106
+ def post1_response
47
107
  '{
48
108
  "_links": {
49
109
  "self": { "href": "/posts/1" }
@@ -60,6 +120,40 @@ module Spinach
60
120
  }'
61
121
  end
62
122
 
123
+ def post2_response
124
+ '{
125
+ "_links": {
126
+ "self": { "href": "/posts/2" }
127
+ },
128
+ "title": "My first blog post",
129
+ "body": "Lorem ipsum dolor sit amet",
130
+ "_embedded": {
131
+ "comments": [
132
+ {
133
+ "title": "Some comment"
134
+ }
135
+ ]
136
+ }
137
+ }'
138
+ end
139
+
140
+ def post3_response
141
+ '{
142
+ "_links": {
143
+ "self": { "href": "/posts/3" }
144
+ },
145
+ "title": "My first blog post",
146
+ "body": "Lorem ipsum dolor sit amet",
147
+ "_embedded": {
148
+ "comments": [
149
+ {
150
+ "title": "Some comment"
151
+ }
152
+ ]
153
+ }
154
+ }'
155
+ end
156
+
63
157
  def page2_response
64
158
  '{
65
159
  "_links": {
data/hyperclient.gemspec CHANGED
@@ -15,8 +15,6 @@ Gem::Specification.new do |gem|
15
15
 
16
16
  gem.add_dependency 'addressable'
17
17
  gem.add_dependency 'faraday', '>= 0.9.0'
18
- gem.add_dependency 'faraday-digestauth'
19
18
  gem.add_dependency 'faraday_hal_middleware'
20
19
  gem.add_dependency 'faraday_middleware'
21
- gem.add_dependency 'net-http-digest_auth'
22
20
  end
@@ -1,6 +1,5 @@
1
1
  require 'faraday_middleware'
2
2
  require 'faraday_hal_middleware'
3
- require_relative '../faraday/connection'
4
3
 
5
4
  module Hyperclient
6
5
  # Public: Exception that is raised when trying to modify an
@@ -30,7 +29,7 @@ module Hyperclient
30
29
  extend Forwardable
31
30
 
32
31
  # Public: Delegates common methods to be used with the Faraday connection.
33
- def_delegators :connection, :basic_auth, :digest_auth, :token_auth, :params, :params=
32
+ def_delegators :connection, :params, :params=
34
33
 
35
34
  # Public: Initializes an EntryPoint.
36
35
  #
@@ -62,8 +61,7 @@ module Hyperclient
62
61
  block
63
62
  else
64
63
  lambda do |conn|
65
- default_faraday_block.call conn
66
- yield conn
64
+ default_faraday_block.call(conn, &block)
67
65
  end
68
66
  end
69
67
  else
@@ -138,11 +136,14 @@ module Hyperclient
138
136
  #
139
137
  # Returns a block.
140
138
  def default_faraday_block
141
- lambda do |connection|
139
+ lambda do |connection, &block|
142
140
  connection.use Faraday::Response::RaiseError
143
141
  connection.use FaradayMiddleware::FollowRedirects
144
142
  connection.request :hal_json
145
143
  connection.response :hal_json, content_type: /\bjson$/
144
+
145
+ block&.call(connection)
146
+
146
147
  connection.adapter :net_http
147
148
  connection.options.params_encoder = Faraday::FlatParamsEncoder
148
149
  end