excon-hypermedia 0.5.2 → 0.5.3
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 +4 -4
- data/.rubocop.yml +4 -1
- data/README.md +6 -3
- data/excon-hypermedia.gemspec +1 -0
- data/lib/excon/hypermedia/middleware.rb +7 -2
- data/lib/excon/hypermedia/middlewares/hypertext_cache_pattern.rb +49 -18
- data/lib/excon/hypermedia/response.rb +3 -7
- data/lib/excon/hypermedia/version.rb +1 -1
- data/test/excon/edgecase_test.rb +11 -37
- data/test/excon/hcp_test.rb +8 -7
- data/test/excon/integration_test.rb +5 -14
- data/test/excon/link_object_test.rb +3 -4
- data/test/excon/links_test.rb +2 -3
- data/test/excon/properties_test.rb +0 -1
- data/test/excon/resource_object_test.rb +1 -2
- data/test/excon/response_test.rb +1 -1
- data/test/support/responses.rb +142 -0
- data/test/support/server.rb +35 -0
- data/test/test_helper.rb +32 -144
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6e498dada7c682834913fd4c4267edd45fe744d2
|
4
|
+
data.tar.gz: 7e399ffe806735ccbf5984ab2d74bcf49646fe68
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 558647f962ced9141ee73e82a83e296d3c88f711cf1b3769f0814ae0b6cfd6cc92ce0814c202fa0f450cf1df1d06cf6e91439f3c765432d96cc20b31c12a60eb
|
7
|
+
data.tar.gz: cc3ad5802a30119dbaead138216298cd371bbf664c1679a1f6a6caaaf6939031cde9b3ea357191bb289d2adadaabccba653af3fa73d00f197556fff8620ca24d
|
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
@@ -280,9 +280,12 @@ pump.resource.weight # => '2kg'
|
|
280
280
|
```
|
281
281
|
|
282
282
|
This feature only works if you are sure the embedded resource is equal to the
|
283
|
-
resource returned by the link relation.
|
284
|
-
|
285
|
-
|
283
|
+
resource returned by the link relation. Also, the embedded resource needs to
|
284
|
+
have a `self` link in order to stub the correct endpoint.
|
285
|
+
|
286
|
+
Because of these requirement, the default configuration has `hcp` disabled, you
|
287
|
+
can either enable it per request (which also enables it for future requests in
|
288
|
+
the chain), or enable it globally:
|
286
289
|
|
287
290
|
```ruby
|
288
291
|
Excon.defaults[:hcp] = true
|
data/excon-hypermedia.gemspec
CHANGED
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.add_development_dependency 'rubocop', '~> 0.40'
|
24
24
|
spec.add_development_dependency 'pry', '~> 0.10'
|
25
25
|
spec.add_development_dependency 'm', '~> 1.5'
|
26
|
+
spec.add_development_dependency 'open4', '~> 1.3'
|
26
27
|
|
27
28
|
spec.add_dependency 'backport_dig' if RUBY_VERSION < '2.3'
|
28
29
|
spec.add_dependency 'excon', '~> 0.49'
|
@@ -17,8 +17,13 @@ module Excon
|
|
17
17
|
#
|
18
18
|
class Middleware < Excon::Middleware::Base
|
19
19
|
def request_call(datum)
|
20
|
-
|
21
|
-
|
20
|
+
# if `hcp` is enabled, insert the `HypertextCachePattern` middleware in
|
21
|
+
# the middleware stack right after this one.
|
22
|
+
if datum[:hcp]
|
23
|
+
orig_stack = @stack
|
24
|
+
@stack = Excon::HyperMedia::Middlewares::HypertextCachePattern.new(orig_stack)
|
25
|
+
end
|
26
|
+
|
22
27
|
super
|
23
28
|
end
|
24
29
|
|
@@ -15,37 +15,68 @@ module Excon
|
|
15
15
|
def request_call(datum)
|
16
16
|
@datum = datum
|
17
17
|
|
18
|
-
|
18
|
+
if stubs.any?
|
19
|
+
# We've created new stubs. The request should be marked as `mocked`
|
20
|
+
# to make sure the stubbed response is returned.
|
21
|
+
datum[:mock] = true
|
19
22
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
# The requested resource might not be part of the embedded resources
|
24
|
+
# so we allow external requests.
|
25
|
+
# datum[:allow_unstubbed_requests] = true
|
26
|
+
|
27
|
+
# Make sure Excon's `Mock` middleware runs after this middleware, as
|
28
|
+
# it might have already triggered in the middleware chain.
|
29
|
+
orig_stack = @stack
|
30
|
+
@stack = Excon::Middleware::Mock.new(orig_stack)
|
31
|
+
end
|
32
|
+
|
33
|
+
super
|
34
|
+
rescue => e
|
35
|
+
raise unless e.class == Excon::Errors::StubNotFound
|
27
36
|
|
37
|
+
# If a request was made to a non-stubbed resource, don't use the Mock
|
38
|
+
# middleware, but simply send the request to the server.
|
39
|
+
@stack = orig_stack
|
28
40
|
super
|
29
41
|
end
|
30
42
|
|
31
|
-
|
43
|
+
def response_call(datum)
|
44
|
+
@datum = datum
|
32
45
|
|
33
|
-
|
34
|
-
|
46
|
+
# After the response is returned, remove any request-specific stubs
|
47
|
+
# from Excon, so they can't be accidentally re-used anymore.
|
48
|
+
embedded.each { |r| (match = matcher(r)) && Excon.unstub(match) }
|
49
|
+
|
50
|
+
super
|
35
51
|
end
|
36
52
|
|
37
|
-
|
38
|
-
|
53
|
+
private
|
54
|
+
|
55
|
+
def stubs
|
56
|
+
embedded.each { |r| (match = matcher(r)) && Excon.stub(match, response(r)) }.compact
|
39
57
|
end
|
40
58
|
|
41
|
-
def
|
42
|
-
|
59
|
+
def matcher(resource)
|
60
|
+
return unless (uri = ::Addressable::URI.parse(resource.dig('_links', 'self', 'href')))
|
61
|
+
|
62
|
+
{
|
63
|
+
scheme: uri.scheme,
|
64
|
+
host: uri.host,
|
65
|
+
path: uri.path,
|
66
|
+
query: uri.query
|
67
|
+
}
|
43
68
|
end
|
44
69
|
|
45
|
-
def
|
46
|
-
|
70
|
+
def response(resource)
|
71
|
+
{
|
72
|
+
body: resource.to_json,
|
73
|
+
hcp: true,
|
74
|
+
headers: { 'Content-Type' => 'application/hal+json', 'X-HCP' => 'true' }
|
75
|
+
}
|
76
|
+
end
|
47
77
|
|
48
|
-
|
78
|
+
def embedded
|
79
|
+
datum[:embedded].to_h.values.flatten
|
49
80
|
end
|
50
81
|
end
|
51
82
|
end
|
@@ -58,19 +58,15 @@ module Excon
|
|
58
58
|
raise UnknownRelationError, "unknown relation: #{name}"
|
59
59
|
end
|
60
60
|
|
61
|
-
options = rel_params(
|
61
|
+
options = rel_params(params.first.to_h)
|
62
62
|
|
63
63
|
link.respond_to?(:to_ary) ? link.map { |l| l.rel(options) } : link.rel(options)
|
64
64
|
end
|
65
65
|
|
66
|
-
def rel_params(
|
66
|
+
def rel_params(params)
|
67
67
|
params.merge(
|
68
68
|
hcp: (params[:hcp].nil? ? response.data[:hcp] : params[:hcp]),
|
69
|
-
|
70
|
-
content_type: response.headers['Content-Type'],
|
71
|
-
embedded: resource._embedded.to_h,
|
72
|
-
relation: name
|
73
|
-
},
|
69
|
+
embedded: resource._embedded.to_h,
|
74
70
|
hypermedia: true
|
75
71
|
)
|
76
72
|
end
|
data/test/excon/edgecase_test.rb
CHANGED
@@ -8,22 +8,8 @@ module Excon
|
|
8
8
|
# Validate edge cases (or: non-happy path)
|
9
9
|
#
|
10
10
|
class EdgeCaseTest < HyperMediaTest
|
11
|
-
def
|
12
|
-
|
13
|
-
Excon.defaults[:middlewares].push(Excon::HyperMedia::Middleware)
|
14
|
-
|
15
|
-
response = { headers: { 'Content-Type' => 'application/hal+json' } }
|
16
|
-
Excon.stub({ path: '/api.json' }, response.merge(body: api_body))
|
17
|
-
Excon.stub({ path: '/empty_json' }, response.merge(body: '{}'))
|
18
|
-
end
|
19
|
-
|
20
|
-
def teardown
|
21
|
-
Excon.stubs.clear
|
22
|
-
Excon.defaults[:middlewares].delete(Excon::HyperMedia::Middleware)
|
23
|
-
end
|
24
|
-
|
25
|
-
def api
|
26
|
-
Excon.get('https://www.example.org/api.json')
|
11
|
+
def empty_json_resource
|
12
|
+
empty_json_response.resource
|
27
13
|
end
|
28
14
|
|
29
15
|
def test_missing_middleware
|
@@ -47,42 +33,30 @@ module Excon
|
|
47
33
|
end
|
48
34
|
|
49
35
|
def test_missing_links
|
50
|
-
|
51
|
-
|
52
|
-
assert_equal({}, resource._links.to_h)
|
36
|
+
assert_equal({}, empty_json_resource._links.to_h)
|
53
37
|
end
|
54
38
|
|
55
39
|
def test_missing_embedded
|
56
|
-
|
57
|
-
|
58
|
-
assert_equal({}, resource._embedded.to_h)
|
40
|
+
assert_equal({}, empty_json_resource._embedded.to_h)
|
59
41
|
end
|
60
42
|
|
61
43
|
def test_missing_properties
|
62
|
-
|
63
|
-
|
64
|
-
assert_equal({}, resource._properties.to_h)
|
44
|
+
assert_equal({}, empty_json_resource._properties.to_h)
|
65
45
|
end
|
66
46
|
|
67
47
|
def test_unknown_property
|
68
|
-
|
69
|
-
|
70
|
-
assert_equal nil, resource._properties.invalid
|
71
|
-
assert_equal nil, resource._properties['invalid']
|
48
|
+
assert_equal nil, api.resource._properties.invalid
|
49
|
+
assert_equal nil, api.resource._properties['invalid']
|
72
50
|
end
|
73
51
|
|
74
52
|
def test_unknown_link
|
75
|
-
|
76
|
-
|
77
|
-
assert_equal nil, resource._links.invalid
|
78
|
-
assert_equal nil, resource._links['invalid']
|
53
|
+
assert_equal nil, empty_json_resource._links.invalid
|
54
|
+
assert_equal nil, empty_json_resource._links['invalid']
|
79
55
|
end
|
80
56
|
|
81
57
|
def test_unknown_embed
|
82
|
-
|
83
|
-
|
84
|
-
assert_equal nil, resource._embedded.invalid
|
85
|
-
assert_equal nil, resource._embedded['invalid']
|
58
|
+
assert_equal nil, api.resource._embedded.invalid
|
59
|
+
assert_equal nil, api.resource._embedded['invalid']
|
86
60
|
end
|
87
61
|
end
|
88
62
|
end
|
data/test/excon/hcp_test.rb
CHANGED
@@ -9,7 +9,7 @@ module Excon
|
|
9
9
|
#
|
10
10
|
class HCPTest < HyperMediaTest
|
11
11
|
def response
|
12
|
-
|
12
|
+
bicycle
|
13
13
|
end
|
14
14
|
|
15
15
|
def test_non_hcp_response
|
@@ -21,16 +21,21 @@ module Excon
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def test_hcp_response_without_existing_response
|
24
|
-
assert Excon.get('
|
24
|
+
assert Excon.get(url('/product/bicycle'), hcp: true)
|
25
25
|
end
|
26
26
|
|
27
27
|
def test_hcp_response_with_missing_embedding
|
28
|
-
api = Excon.get('https://www.example.org/api.json')
|
29
28
|
response = api.rel('product', expand: { uid: 'bicycle' }, hcp: true).get
|
30
29
|
|
31
30
|
assert_equal nil, response[:hcp]
|
32
31
|
end
|
33
32
|
|
33
|
+
def test_hcp_response_with_embedding_but_missing_embed_for_request
|
34
|
+
handlebar = response.rel('handlebar', hcp: true).get
|
35
|
+
|
36
|
+
assert_equal nil, handlebar[:hcp]
|
37
|
+
end
|
38
|
+
|
34
39
|
def test_hcp_response_with_embedded_array
|
35
40
|
wheels = response.rel('wheels', hcp: true)
|
36
41
|
|
@@ -44,10 +49,6 @@ module Excon
|
|
44
49
|
assert response[:hcp]
|
45
50
|
end
|
46
51
|
|
47
|
-
def test_hcp_not_working_for_non_get_requests
|
48
|
-
assert_equal nil, response.rel('pump', hcp: true).post[:hcp]
|
49
|
-
end
|
50
|
-
|
51
52
|
def test_hcp_resource
|
52
53
|
resource = response.rel('pump', hcp: true).get.resource
|
53
54
|
|
@@ -10,20 +10,16 @@ module Excon
|
|
10
10
|
# Verifies the Excon connection consuming HyperMedia APIs.
|
11
11
|
#
|
12
12
|
class IntegrationTest < HyperMediaTest
|
13
|
-
def api
|
14
|
-
Excon.get('https://www.example.org/api.json')
|
15
|
-
end
|
16
|
-
|
17
13
|
def test_request
|
18
14
|
response = api.rel('product', expand: { uid: 'bicycle' }).get
|
19
15
|
|
20
|
-
assert response.body.include?('
|
16
|
+
assert response.body.include?('/product/bicycle')
|
21
17
|
end
|
22
18
|
|
23
19
|
def test_request_using_link_rel
|
24
20
|
response = api.resource._links.product.rel(expand: { uid: 'bicycle' }).get
|
25
21
|
|
26
|
-
assert response.body.include?('
|
22
|
+
assert response.body.include?('/product/bicycle')
|
27
23
|
end
|
28
24
|
|
29
25
|
def test_nested_request
|
@@ -45,7 +41,7 @@ module Excon
|
|
45
41
|
def test_expand_in_get
|
46
42
|
response = api.rel('product').get(expand: { uid: 'bicycle' })
|
47
43
|
|
48
|
-
assert response.body.include?('
|
44
|
+
assert response.body.include?('/product/bicycle')
|
49
45
|
end
|
50
46
|
|
51
47
|
def test_link
|
@@ -89,14 +85,9 @@ module Excon
|
|
89
85
|
end
|
90
86
|
|
91
87
|
def test_request_with_json_content_type
|
92
|
-
|
93
|
-
response = api.rel('product', expand: { uid: 'bicycle' }).get
|
94
|
-
|
95
|
-
assert response.body.include?('https://www.example.org/product/bicycle')
|
96
|
-
end
|
88
|
+
response = api_v2.rel('product', expand: { uid: 'bicycle' }).get
|
97
89
|
|
98
|
-
|
99
|
-
Excon.stubs.clear
|
90
|
+
assert response.body.include?('/product/bicycle')
|
100
91
|
end
|
101
92
|
end
|
102
93
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
# rubocop:disable Metrics/MethodLength
|
3
2
|
|
4
3
|
require_relative '../test_helper'
|
5
4
|
|
@@ -10,17 +9,17 @@ module Excon
|
|
10
9
|
#
|
11
10
|
class LinkTest < Minitest::Test
|
12
11
|
def self
|
13
|
-
'{ "href": "https://
|
12
|
+
'{ "href": "https://example.org/hello" }'
|
14
13
|
end
|
15
14
|
|
16
15
|
def templated
|
17
|
-
'{ "href": "https://
|
16
|
+
'{ "href": "https://example.org/hello/{receiver}", "templated": "true" }'
|
18
17
|
end
|
19
18
|
|
20
19
|
def full
|
21
20
|
<<-EOF
|
22
21
|
{
|
23
|
-
"href": "https://
|
22
|
+
"href": "https://example.org/goodbye/{receiver}",
|
24
23
|
"templated": "true",
|
25
24
|
"type": "json",
|
26
25
|
"deprecation": true,
|
data/test/excon/links_test.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
# rubocop:disable Metrics/MethodLength
|
3
2
|
|
4
3
|
require_relative '../test_helper'
|
5
4
|
|
@@ -14,10 +13,10 @@ module Excon
|
|
14
13
|
{
|
15
14
|
"_links": {
|
16
15
|
"self": {
|
17
|
-
"href": "https://
|
16
|
+
"href": "https://example.org/product/bicycle"
|
18
17
|
},
|
19
18
|
"parts": {
|
20
|
-
"href": "https://
|
19
|
+
"href": "https://example.org/product/bicycle/parts"
|
21
20
|
}
|
22
21
|
}
|
23
22
|
}
|
@@ -1,5 +1,4 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
# rubocop:disable Metrics/MethodLength
|
3
2
|
|
4
3
|
require_relative '../test_helper'
|
5
4
|
|
@@ -14,7 +13,7 @@ module Excon
|
|
14
13
|
{
|
15
14
|
"_links": {
|
16
15
|
"hello": {
|
17
|
-
"href": "
|
16
|
+
"href": "https://example.org/hello/{location}"
|
18
17
|
}
|
19
18
|
},
|
20
19
|
"uid": "universe",
|
data/test/excon/response_test.rb
CHANGED
@@ -0,0 +1,142 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# rubocop:disable Metrics/MethodLength
|
3
|
+
# rubocop:disable Metrics/ModuleLength
|
4
|
+
|
5
|
+
# :no-doc:
|
6
|
+
module Test
|
7
|
+
# :no-doc:
|
8
|
+
module Response
|
9
|
+
module_function
|
10
|
+
|
11
|
+
def api_body
|
12
|
+
<<-EOF
|
13
|
+
{
|
14
|
+
"_links": {
|
15
|
+
"self": {
|
16
|
+
"href": "http://localhost:8000/api.json"
|
17
|
+
},
|
18
|
+
"product": {
|
19
|
+
"href": "http://localhost:8000/product/{uid}",
|
20
|
+
"templated": true
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}
|
24
|
+
EOF
|
25
|
+
end
|
26
|
+
|
27
|
+
def bicycle_body
|
28
|
+
<<-EOF
|
29
|
+
{
|
30
|
+
"_links": {
|
31
|
+
"self": {
|
32
|
+
"href": "http://localhost:8000/product/bicycle"
|
33
|
+
},
|
34
|
+
"handlebar": {
|
35
|
+
"href": "http://localhost:8000/product/handlebar"
|
36
|
+
},
|
37
|
+
"object_id": {
|
38
|
+
"href": "http://localhost:8000/product/bicycle/object_id_as_text"
|
39
|
+
},
|
40
|
+
"pump": {
|
41
|
+
"href": "http://localhost:8000/product/pump"
|
42
|
+
},
|
43
|
+
"wheels": [
|
44
|
+
{ "href": "http://localhost:8000/product/bicycle/wheels/front" },
|
45
|
+
{ "href": "http://localhost:8000/product/bicycle/wheels/rear" }
|
46
|
+
]
|
47
|
+
},
|
48
|
+
"bike-type": "Mountain Bike",
|
49
|
+
"BMX": false,
|
50
|
+
"derailleurs": {
|
51
|
+
"back": 7,
|
52
|
+
"front": 3
|
53
|
+
},
|
54
|
+
"name": "bicycle",
|
55
|
+
"reflectors": true,
|
56
|
+
"_embedded": {
|
57
|
+
"pump": #{pump_body},
|
58
|
+
"wheels": [#{front_wheel_body}, #{rear_wheel_body}]
|
59
|
+
}
|
60
|
+
}
|
61
|
+
EOF
|
62
|
+
end
|
63
|
+
|
64
|
+
def handlebar_body
|
65
|
+
<<-EOF
|
66
|
+
{
|
67
|
+
"_links": {
|
68
|
+
"self": {
|
69
|
+
"href": "http://localhost:8000/product/handlebar"
|
70
|
+
}
|
71
|
+
},
|
72
|
+
"material": "Carbon fiber",
|
73
|
+
"reach": "75mm",
|
74
|
+
"bend": "compact"
|
75
|
+
}
|
76
|
+
EOF
|
77
|
+
end
|
78
|
+
|
79
|
+
def pump_body
|
80
|
+
<<-EOF
|
81
|
+
{
|
82
|
+
"_links": {
|
83
|
+
"self": {
|
84
|
+
"href": "http://localhost:8000/product/pump"
|
85
|
+
},
|
86
|
+
"parts": {
|
87
|
+
"href": "http://localhost:8000/product/pump/parts"
|
88
|
+
}
|
89
|
+
},
|
90
|
+
"weight": "2kg",
|
91
|
+
"type": "Floor Pump",
|
92
|
+
"valve-type": "Presta",
|
93
|
+
"_embedded": {
|
94
|
+
"parts": #{parts_body}
|
95
|
+
}
|
96
|
+
|
97
|
+
}
|
98
|
+
EOF
|
99
|
+
end
|
100
|
+
|
101
|
+
def parts_body
|
102
|
+
<<-EOF
|
103
|
+
{
|
104
|
+
"_links": {
|
105
|
+
"self": {
|
106
|
+
"href": "http://localhost:8000/product/pump/parts"
|
107
|
+
}
|
108
|
+
},
|
109
|
+
"count": 47
|
110
|
+
}
|
111
|
+
EOF
|
112
|
+
end
|
113
|
+
|
114
|
+
def rear_wheel_body
|
115
|
+
<<-EOF
|
116
|
+
{
|
117
|
+
"_links": {
|
118
|
+
"self": {
|
119
|
+
"href": "http://localhost:8000/product/bicycle/wheels/rear"
|
120
|
+
}
|
121
|
+
},
|
122
|
+
"position": "rear",
|
123
|
+
"lacing_pattern": "Radial"
|
124
|
+
}
|
125
|
+
EOF
|
126
|
+
end
|
127
|
+
|
128
|
+
def front_wheel_body
|
129
|
+
<<-EOF
|
130
|
+
{
|
131
|
+
"_links": {
|
132
|
+
"self": {
|
133
|
+
"href": "http://localhost:8000/product/bicycle/wheels/front"
|
134
|
+
}
|
135
|
+
},
|
136
|
+
"position": "front",
|
137
|
+
"lacing_pattern": "Radial/2-Cross"
|
138
|
+
}
|
139
|
+
EOF
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'webrick'
|
5
|
+
require 'logger'
|
6
|
+
require_relative 'responses'
|
7
|
+
|
8
|
+
server = WEBrick::HTTPServer.new(Port: 8000, Logger: Logger.new(STDERR))
|
9
|
+
|
10
|
+
def body(name)
|
11
|
+
Test::Response.send("#{name}_body")
|
12
|
+
end
|
13
|
+
|
14
|
+
endpoints = {
|
15
|
+
'/empty_json' => { body: '{}' },
|
16
|
+
'/api.json' => { body: body(:api) },
|
17
|
+
'/product/bicycle' => { body: body(:bicycle) },
|
18
|
+
'/product/bicycle/wheels/front' => { body: body(:front_wheel) },
|
19
|
+
'/product/bicycle/wheels/rear' => { body: body(:rear_wheel) },
|
20
|
+
'/product/pump' => { body: body(:pump) },
|
21
|
+
'/product/pump/parts' => { body: body(:parts) },
|
22
|
+
'/product/handlebar' => { body: body(:handlebar) },
|
23
|
+
'/api_v2.json' => { body: body(:api), headers: { 'Content-Type' => 'application/json' } }
|
24
|
+
}
|
25
|
+
|
26
|
+
endpoints.each do |path, params|
|
27
|
+
server.mount_proc(path) do |_, response|
|
28
|
+
response['Content-Type'] = 'application/hal+json'
|
29
|
+
params[:headers].to_h.each { |k, v| response[k] = v }
|
30
|
+
|
31
|
+
response.body = params[:body]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
server.start
|
data/test/test_helper.rb
CHANGED
@@ -1,171 +1,59 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
# rubocop:disable Metrics/MethodLength
|
3
|
-
# rubocop:disable Metrics/LineLength
|
4
|
-
# rubocop:disable Metrics/ClassLength
|
5
|
-
# rubocop:disable Metrics/AbcSize
|
6
2
|
|
7
3
|
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
8
4
|
require 'excon/hypermedia'
|
9
5
|
require 'minitest/autorun'
|
6
|
+
require 'open4'
|
7
|
+
require_relative 'support/responses'
|
8
|
+
|
9
|
+
Excon.defaults.merge!(
|
10
|
+
connect_timeout: 1,
|
11
|
+
read_timeout: 1,
|
12
|
+
write_timeout: 1
|
13
|
+
)
|
14
|
+
|
15
|
+
@server_pid, _, _, e = Open4.popen4(File.expand_path('support/server.rb', __dir__))
|
16
|
+
until e.gets =~ /HTTPServer#start/; end
|
17
|
+
|
18
|
+
Minitest.after_run do
|
19
|
+
Process.kill(9, @server_pid)
|
20
|
+
Process.wait(@server_pid)
|
21
|
+
end
|
10
22
|
|
11
23
|
module Excon
|
12
24
|
# HyperMediaTest
|
13
25
|
#
|
14
26
|
class HyperMediaTest < Minitest::Test
|
15
|
-
def
|
16
|
-
Excon.
|
17
|
-
Excon.defaults[:middlewares].push(Excon::HyperMedia::Middleware)
|
18
|
-
|
19
|
-
response = { headers: { 'Content-Type' => 'application/hal+json' } }
|
20
|
-
Excon.stub({ method: :get, path: '/api.json' }, response.merge(body: api_body))
|
21
|
-
Excon.stub({ method: :get, path: '/product/bicycle' }, response.merge(body: bicycle_body))
|
22
|
-
Excon.stub({ method: :get, path: '/product/bicycle/wheels/front' }, response.merge(body: front_wheel_body))
|
23
|
-
Excon.stub({ method: :get, path: '/product/bicycle/wheels/rear' }, response.merge(body: rear_wheel_body))
|
24
|
-
Excon.stub({ path: '/product/pump' }, response.merge(body: pump_body))
|
25
|
-
Excon.stub({ method: :get, path: '/product/pump/parts' }, response.merge(body: parts_body))
|
26
|
-
Excon.stub({ method: :get, path: '/product/handlebar' }, response.merge(body: handlebar_body))
|
27
|
-
Excon.stub({ method: :get, path: '/api_v2.json' }, body: api_body, headers: { 'Content-Type' => 'application/json' })
|
28
|
-
end
|
29
|
-
|
30
|
-
def teardown
|
31
|
-
Excon.stubs.clear
|
32
|
-
Excon.defaults[:middlewares].delete(Excon::HyperMedia::Middleware)
|
33
|
-
Excon.defaults[:mock] = true
|
27
|
+
def api
|
28
|
+
Excon.get('http://localhost:8000/api.json')
|
34
29
|
end
|
35
30
|
|
36
|
-
def
|
37
|
-
|
31
|
+
def api_v2
|
32
|
+
Excon.get('http://localhost:8000/api_v2.json', hypermedia: true)
|
38
33
|
end
|
39
34
|
|
40
|
-
def
|
41
|
-
|
42
|
-
{
|
43
|
-
"_links": {
|
44
|
-
"self": {
|
45
|
-
"href": "https://www.example.org/api.json"
|
46
|
-
},
|
47
|
-
"product": {
|
48
|
-
"href": "https://www.example.org/product/{uid}",
|
49
|
-
"templated": true
|
50
|
-
}
|
51
|
-
}
|
52
|
-
}
|
53
|
-
EOF
|
35
|
+
def empty_json_response
|
36
|
+
Excon.get('http://localhost:8000/empty_json')
|
54
37
|
end
|
55
38
|
|
56
|
-
def
|
57
|
-
|
58
|
-
{
|
59
|
-
"_links": {
|
60
|
-
"self": {
|
61
|
-
"href": "https://www.example.org/product/bicycle"
|
62
|
-
},
|
63
|
-
"handlebar": {
|
64
|
-
"href": "https://www.example.org/product/handlebar"
|
65
|
-
},
|
66
|
-
"object_id": {
|
67
|
-
"href": "https://www.example.org/product/bicycle/object_id_as_text"
|
68
|
-
},
|
69
|
-
"pump": {
|
70
|
-
"href": "https://www.example.org/product/pump"
|
71
|
-
},
|
72
|
-
"wheels": [
|
73
|
-
{ "href": "https://www.example.org/product/bicycle/wheels/front" },
|
74
|
-
{ "href": "https://www.example.org/product/bicycle/wheels/rear" }
|
75
|
-
]
|
76
|
-
},
|
77
|
-
"bike-type": "Mountain Bike",
|
78
|
-
"BMX": false,
|
79
|
-
"derailleurs": {
|
80
|
-
"back": 7,
|
81
|
-
"front": 3
|
82
|
-
},
|
83
|
-
"name": "bicycle",
|
84
|
-
"reflectors": true,
|
85
|
-
"_embedded": {
|
86
|
-
"pump": #{pump_body},
|
87
|
-
"wheels": [#{front_wheel_body}, #{rear_wheel_body}]
|
88
|
-
}
|
89
|
-
}
|
90
|
-
EOF
|
39
|
+
def bicycle
|
40
|
+
@bicycle ||= Excon.get('http://localhost:8000/product/bicycle')
|
91
41
|
end
|
92
42
|
|
93
|
-
def
|
94
|
-
|
95
|
-
{
|
96
|
-
"_links": {
|
97
|
-
"self": {
|
98
|
-
"href": "https://www.example.org/product/handlebar"
|
99
|
-
}
|
100
|
-
},
|
101
|
-
"material": "Carbon fiber",
|
102
|
-
"reach": "75mm",
|
103
|
-
"bend": "compact"
|
104
|
-
}
|
105
|
-
EOF
|
106
|
-
end
|
107
|
-
|
108
|
-
def pump_body
|
109
|
-
<<-EOF
|
110
|
-
{
|
111
|
-
"_links": {
|
112
|
-
"self": {
|
113
|
-
"href": "https://www.example.org/product/pump"
|
114
|
-
},
|
115
|
-
"parts": {
|
116
|
-
"href": "https://www.example.org/product/pump/parts"
|
117
|
-
}
|
118
|
-
},
|
119
|
-
"weight": "2kg",
|
120
|
-
"type": "Floor Pump",
|
121
|
-
"valve-type": "Presta",
|
122
|
-
"_embedded": {
|
123
|
-
"parts": #{parts_body}
|
124
|
-
}
|
125
|
-
|
126
|
-
}
|
127
|
-
EOF
|
43
|
+
def setup
|
44
|
+
Excon.defaults[:middlewares].push(Excon::HyperMedia::Middleware)
|
128
45
|
end
|
129
46
|
|
130
|
-
def
|
131
|
-
|
132
|
-
{
|
133
|
-
"_links": {
|
134
|
-
"self": {
|
135
|
-
"href": "https://www.example.org/product/pump/parts"
|
136
|
-
}
|
137
|
-
},
|
138
|
-
"count": 47
|
139
|
-
}
|
140
|
-
EOF
|
47
|
+
def teardown
|
48
|
+
Excon.defaults[:middlewares].delete(Excon::HyperMedia::Middleware)
|
141
49
|
end
|
142
50
|
|
143
|
-
def
|
144
|
-
|
145
|
-
{
|
146
|
-
"_links": {
|
147
|
-
"self": {
|
148
|
-
"href": "https://www.example.org/product/bicycle/wheels/rear"
|
149
|
-
}
|
150
|
-
},
|
151
|
-
"position": "rear",
|
152
|
-
"lacing_pattern": "Radial"
|
153
|
-
}
|
154
|
-
EOF
|
51
|
+
def data(name)
|
52
|
+
JSON.parse(Test::Response.send("#{name}_body"))
|
155
53
|
end
|
156
54
|
|
157
|
-
def
|
158
|
-
|
159
|
-
{
|
160
|
-
"_links": {
|
161
|
-
"self": {
|
162
|
-
"href": "https://www.example.org/product/bicycle/wheels/front"
|
163
|
-
}
|
164
|
-
},
|
165
|
-
"position": "front",
|
166
|
-
"lacing_pattern": "Radial/2-Cross"
|
167
|
-
}
|
168
|
-
EOF
|
55
|
+
def url(path)
|
56
|
+
File.join('http://localhost:8000', path)
|
169
57
|
end
|
170
58
|
end
|
171
59
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: excon-hypermedia
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jean
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-05-
|
12
|
+
date: 2016-05-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -95,6 +95,20 @@ dependencies:
|
|
95
95
|
- - "~>"
|
96
96
|
- !ruby/object:Gem::Version
|
97
97
|
version: '1.5'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: open4
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - "~>"
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '1.3'
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - "~>"
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '1.3'
|
98
112
|
- !ruby/object:Gem::Dependency
|
99
113
|
name: excon
|
100
114
|
requirement: !ruby/object:Gem::Requirement
|
@@ -160,6 +174,8 @@ files:
|
|
160
174
|
- test/excon/properties_test.rb
|
161
175
|
- test/excon/resource_object_test.rb
|
162
176
|
- test/excon/response_test.rb
|
177
|
+
- test/support/responses.rb
|
178
|
+
- test/support/server.rb
|
163
179
|
- test/test_helper.rb
|
164
180
|
homepage: https://github.com/JeanMertz/excon-hypermedia
|
165
181
|
licenses:
|