hal-client 3.16.0 → 3.17.0
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/.gitignore +1 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -1
- data/hal-client.gemspec +2 -1
- data/lib/hal_client/links_section.rb +8 -3
- data/lib/hal_client/representation.rb +22 -20
- data/lib/hal_client/version.rb +1 -1
- data/lib/hal_client.rb +17 -19
- data/spec/hal_client/collection_spec.rb +2 -4
- data/spec/hal_client/curie_resolver_spec.rb +1 -3
- data/spec/hal_client/link_spec.rb +1 -3
- data/spec/hal_client/links_section_spec.rb +4 -5
- data/spec/hal_client/representation_editor_spec.rb +0 -1
- data/spec/hal_client/representation_set_spec.rb +14 -16
- data/spec/hal_client/representation_spec.rb +30 -32
- data/spec/hal_client_spec.rb +83 -9
- data/spec/spec_helper.rb +74 -2
- metadata +19 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4c738c6f35a8c627363d55bde0e10116bf46eb1b
|
4
|
+
data.tar.gz: 32b562905f475064e94fbf2128222292dc44bc4c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cf65e375001c9c167d557fe6345c58cdb07d5d70d63da052d7ce82392f9805002cbe6e91c703879fbe3f3c7cede65a2c88a74cf0943fa7fd4e825ad52541a263
|
7
|
+
data.tar.gz: 6749283d49cc6f3aa0ae7f37e5aeda09c08ad875d4206a8250fbac21200ca7afc09e42a6388bdd392bb8e667b88b574751771f1d6275e92892d725a663b9a9c9
|
data/.gitignore
CHANGED
data/.rspec
ADDED
data/.travis.yml
CHANGED
data/hal-client.gemspec
CHANGED
@@ -24,7 +24,8 @@ Gem::Specification.new do |spec|
|
|
24
24
|
|
25
25
|
spec.add_development_dependency "bundler", "~> 1.5"
|
26
26
|
spec.add_development_dependency "rake", "~> 10.1"
|
27
|
-
spec.add_development_dependency "rspec", "~> 3.
|
27
|
+
spec.add_development_dependency "rspec", "~> 3.5"
|
28
28
|
spec.add_development_dependency "webmock", ["~> 1.17", ">= 1.17.4"]
|
29
29
|
spec.add_development_dependency "rspec-collection_matchers"
|
30
|
+
spec.add_development_dependency "pry"
|
30
31
|
end
|
@@ -2,6 +2,13 @@ class HalClient
|
|
2
2
|
|
3
3
|
# Encapsulates a "_links" section.
|
4
4
|
class LinksSection
|
5
|
+
|
6
|
+
NO_RELATED_RESOURCE = ->(link_rel) {
|
7
|
+
raise KeyError, "No resources are related via `#{link_rel}`"
|
8
|
+
}
|
9
|
+
|
10
|
+
private_constant :NO_RELATED_RESOURCE
|
11
|
+
|
5
12
|
# section - json hash for the links section
|
6
13
|
# base_url - base URL with which to resolve relative URLs
|
7
14
|
def initialize(section, opts={} )
|
@@ -27,9 +34,7 @@ class HalClient
|
|
27
34
|
# Raises KeyError if the specified link_rel is not present and no
|
28
35
|
# default_value or default_proc are provided.
|
29
36
|
def hrefs(link_rel, &default_proc)
|
30
|
-
default_proc ||=
|
31
|
-
raise KeyError, "No resources are related via `#{link_rel}`"
|
32
|
-
}
|
37
|
+
default_proc ||= NO_RELATED_RESOURCE
|
33
38
|
|
34
39
|
return default_proc.call(link_rel) unless section.key? link_rel
|
35
40
|
|
@@ -15,6 +15,20 @@ class HalClient
|
|
15
15
|
# https://tools.ietf.org/html/draft-kelly-json-hal-07#section-4.1
|
16
16
|
RESERVED_PROPERTIES = ['_links', '_embedded'].freeze
|
17
17
|
|
18
|
+
NO_RELATED_RESOURCE = ->(link_rel) {
|
19
|
+
raise KeyError, "No resources are related via `#{link_rel}`"
|
20
|
+
}
|
21
|
+
|
22
|
+
NO_EMBED_FOUND = ->(link_rel) {
|
23
|
+
raise KeyError, "#{link_rel} embed not found"
|
24
|
+
}
|
25
|
+
|
26
|
+
NO_LINK_FOUND = ->(link_rel, _options) {
|
27
|
+
raise KeyError, "#{link_rel} link not found"
|
28
|
+
}
|
29
|
+
|
30
|
+
private_constant :NO_RELATED_RESOURCE, :NO_EMBED_FOUND, :NO_LINK_FOUND
|
31
|
+
|
18
32
|
# Create a new Representation
|
19
33
|
#
|
20
34
|
# options - name parameters
|
@@ -145,11 +159,7 @@ class HalClient
|
|
145
159
|
#
|
146
160
|
# link_rel - The link rel of interest
|
147
161
|
def related?(link_rel)
|
148
|
-
|
149
|
-
true
|
150
|
-
|
151
|
-
rescue KeyError
|
152
|
-
false
|
162
|
+
!!(linked(link_rel) { false } || embedded(link_rel) { false })
|
153
163
|
end
|
154
164
|
alias_method :has_related?, :related?
|
155
165
|
|
@@ -166,9 +176,7 @@ class HalClient
|
|
166
176
|
# Raises KeyError if the specified link does not exist
|
167
177
|
# and no default_proc is provided.
|
168
178
|
def related(link_rel, options = {}, &default_proc)
|
169
|
-
default_proc ||=
|
170
|
-
raise KeyError, "No resources are related via `#{link_rel}`"
|
171
|
-
}
|
179
|
+
default_proc ||= NO_RELATED_RESOURCE
|
172
180
|
|
173
181
|
embedded = embedded(link_rel) { nil }
|
174
182
|
linked = linked(link_rel, options) { nil }
|
@@ -231,9 +239,7 @@ class HalClient
|
|
231
239
|
# Raises KeyError if the specified link does not exist
|
232
240
|
# and no default_proc is provided.
|
233
241
|
def raw_related_hrefs(link_rel, &default_proc)
|
234
|
-
default_proc ||=
|
235
|
-
raise KeyError, "No resources are related via `#{link_rel}`"
|
236
|
-
}
|
242
|
+
default_proc ||= NO_RELATED_RESOURCE
|
237
243
|
|
238
244
|
embedded = embedded(link_rel) { nil }
|
239
245
|
linked = links.hrefs(link_rel) { nil }
|
@@ -346,23 +352,19 @@ class HalClient
|
|
346
352
|
end
|
347
353
|
|
348
354
|
def embedded(link_rel, &default_proc)
|
349
|
-
default_proc ||=
|
350
|
-
fail KeyError, "#{link_rel} embed not found"
|
351
|
-
}
|
355
|
+
default_proc ||= NO_EMBED_FOUND
|
352
356
|
|
353
357
|
relations = embedded_section.fetch(link_rel) { MISSING }
|
354
358
|
return default_proc.call(link_rel) if relations == MISSING
|
355
359
|
|
356
360
|
(boxed relations).map{|it| Representation.new hal_client: hal_client, parsed_json: it}
|
357
361
|
|
358
|
-
rescue InvalidRepresentationError
|
362
|
+
rescue InvalidRepresentationError
|
359
363
|
fail InvalidRepresentationError, "/_embedded/#{jpointer_esc(link_rel)} is not a valid representation"
|
360
364
|
end
|
361
365
|
|
362
|
-
def linked(link_rel, options, &default_proc)
|
363
|
-
default_proc ||=
|
364
|
-
fail KeyError, "#{link_rel} link not found"
|
365
|
-
}
|
366
|
+
def linked(link_rel, options = {}, &default_proc)
|
367
|
+
default_proc ||= NO_LINK_FOUND
|
366
368
|
|
367
369
|
relations = links.hrefs(link_rel) { MISSING }
|
368
370
|
return default_proc.call(link_rel, options) if relations == MISSING
|
@@ -376,7 +378,7 @@ class HalClient
|
|
376
378
|
end }
|
377
379
|
.map {|href| Representation.new href: href, hal_client: hal_client }
|
378
380
|
|
379
|
-
rescue InvalidRepresentationError
|
381
|
+
rescue InvalidRepresentationError
|
380
382
|
fail InvalidRepresentationError, "/_links/#{jpointer_esc(link_rel)} is not a valid link"
|
381
383
|
end
|
382
384
|
|
data/lib/hal_client/version.rb
CHANGED
data/lib/hal_client.rb
CHANGED
@@ -44,6 +44,7 @@ class HalClient
|
|
44
44
|
@base_client ||= options[:base_client]
|
45
45
|
@logger = options.fetch(:logger, NullLogger.new)
|
46
46
|
@timeout = options.fetch(:timeout, Float::INFINITY)
|
47
|
+
@base_client_with_headers = {}
|
47
48
|
|
48
49
|
default_message_request_headers.set('Accept', options[:accept]) if
|
49
50
|
options[:accept]
|
@@ -185,7 +186,7 @@ class HalClient
|
|
185
186
|
begin
|
186
187
|
Representation.new(hal_client: self, parsed_json: MultiJson.load(resp.to_s),
|
187
188
|
href: location)
|
188
|
-
rescue MultiJson::ParseError, InvalidRepresentationError
|
189
|
+
rescue MultiJson::ParseError, InvalidRepresentationError
|
189
190
|
if location
|
190
191
|
# response doesn't have a HAL body but we know what resource
|
191
192
|
# was created so we can be helpful.
|
@@ -213,13 +214,9 @@ class HalClient
|
|
213
214
|
# options
|
214
215
|
# :override_headers -
|
215
216
|
def client_for_get(options={})
|
216
|
-
|
217
|
+
headers = default_message_request_headers.merge(options[:override_headers])
|
217
218
|
|
218
|
-
|
219
|
-
@client_for_get ||= base_client.with_headers(default_message_request_headers)
|
220
|
-
else
|
221
|
-
client_for_get.with_headers(override_headers)
|
222
|
-
end
|
219
|
+
base_client_with_headers(headers)
|
223
220
|
end
|
224
221
|
|
225
222
|
# Returns the HTTP client to be used to make post requests.
|
@@ -227,19 +224,24 @@ class HalClient
|
|
227
224
|
# options
|
228
225
|
# :override_headers -
|
229
226
|
def client_for_post(options={})
|
230
|
-
|
227
|
+
headers = default_entity_and_message_request_headers.merge(options[:override_headers])
|
231
228
|
|
232
|
-
|
233
|
-
@client_for_post ||=
|
234
|
-
base_client.with_headers(default_entity_and_message_request_headers)
|
235
|
-
else
|
236
|
-
client_for_post.with_headers(override_headers)
|
237
|
-
end
|
229
|
+
base_client_with_headers(headers)
|
238
230
|
end
|
239
231
|
|
240
232
|
# Returns an HTTP client.
|
241
233
|
def base_client
|
242
|
-
@base_client ||=
|
234
|
+
@base_client ||= begin
|
235
|
+
logger.debug 'Created base_client'
|
236
|
+
HTTP::Client.new(follow: true)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
def base_client_with_headers(headers)
|
241
|
+
@base_client_with_headers[headers.to_h] ||= begin
|
242
|
+
logger.debug { "Created base_client with headers #{headers.inspect}" }
|
243
|
+
base_client.with_headers(headers)
|
244
|
+
end
|
243
245
|
end
|
244
246
|
|
245
247
|
attr_reader :default_entity_request_headers, :default_message_request_headers
|
@@ -249,10 +251,6 @@ class HalClient
|
|
249
251
|
default_message_request_headers.merge(default_entity_request_headers)
|
250
252
|
end
|
251
253
|
|
252
|
-
def default_entity_request_headers
|
253
|
-
@default_entity_request_headers
|
254
|
-
end
|
255
|
-
|
256
254
|
def entity_header_field?(field_name)
|
257
255
|
[:content_type, /^content-type$/i].any?{|pat| pat === field_name}
|
258
256
|
end
|
@@ -1,8 +1,6 @@
|
|
1
|
-
require_relative "../spec_helper"
|
2
|
-
|
3
1
|
require 'hal_client/collection'
|
4
2
|
|
5
|
-
describe HalClient::Collection do
|
3
|
+
RSpec.describe HalClient::Collection do
|
6
4
|
# BACKGROUND
|
7
5
|
|
8
6
|
shared_context "multi-item, multi-page" do
|
@@ -81,7 +79,7 @@ describe HalClient::Collection do
|
|
81
79
|
context do
|
82
80
|
include_context "multi-item, multi-page"
|
83
81
|
|
84
|
-
specify { expect { collection.count }.to raise_exception }
|
82
|
+
specify { expect { collection.count }.to raise_exception(NotImplementedError) }
|
85
83
|
end
|
86
84
|
end
|
87
85
|
|
@@ -1,8 +1,6 @@
|
|
1
|
-
require_relative "../spec_helper"
|
2
|
-
|
3
1
|
require 'hal_client/curie_resolver'
|
4
2
|
|
5
|
-
describe HalClient::CurieResolver do
|
3
|
+
RSpec.describe HalClient::CurieResolver do
|
6
4
|
describe "#new" do
|
7
5
|
it "takes an array of curie definitions" do
|
8
6
|
expect(described_class.new([f_ns, b_ns])).to be_kind_of described_class
|
@@ -1,7 +1,6 @@
|
|
1
|
-
require "spec_helper"
|
2
1
|
require 'hal-client'
|
3
2
|
|
4
|
-
describe HalClient::LinksSection, "namespaces embedded" do
|
3
|
+
RSpec.describe HalClient::LinksSection, "namespaces embedded" do
|
5
4
|
subject(:section) {
|
6
5
|
described_class.new(raw_section,
|
7
6
|
base_url: Addressable::URI.parse("http://example.com/foo"))
|
@@ -21,7 +20,7 @@ describe HalClient::LinksSection, "namespaces embedded" do
|
|
21
20
|
|
22
21
|
specify { expect(section.hrefs(fully_qualified_second_rel))
|
23
22
|
.to contain_exactly "http://example.com/bar", "http://example.com/baz" }
|
24
|
-
|
23
|
+
|
25
24
|
specify { expect(section.hrefs("ns2:second"))
|
26
25
|
.to contain_exactly "http://example.com/bar", "http://example.com/baz" }
|
27
26
|
|
@@ -56,7 +55,7 @@ describe HalClient::LinksSection, "namespaces embedded" do
|
|
56
55
|
end
|
57
56
|
end
|
58
57
|
|
59
|
-
describe HalClient::LinksSection, "invalid" do
|
58
|
+
RSpec.describe HalClient::LinksSection, "invalid" do
|
60
59
|
subject(:section) {
|
61
60
|
described_class.new(raw_section,
|
62
61
|
base_url: Addressable::URI.parse("http://example.com/"))
|
@@ -69,4 +68,4 @@ describe HalClient::LinksSection, "invalid" do
|
|
69
68
|
{ "bareurl" => "http://example.com/boom" }
|
70
69
|
}
|
71
70
|
|
72
|
-
end
|
71
|
+
end
|
@@ -1,14 +1,12 @@
|
|
1
|
-
require_relative '../spec_helper'
|
2
|
-
|
3
1
|
require 'hal_client'
|
4
2
|
require 'hal_client/representation'
|
5
3
|
require 'hal_client/representation_set'
|
6
4
|
|
7
|
-
describe HalClient::RepresentationSet do
|
5
|
+
RSpec.describe HalClient::RepresentationSet do
|
8
6
|
describe "#new" do
|
9
7
|
let!(:return_val) { described_class.new([foo_repr, bar_repr]) }
|
10
|
-
it {
|
11
|
-
it {
|
8
|
+
it { is_expected.to be_kind_of described_class }
|
9
|
+
it { is_expected.to have(2).items }
|
12
10
|
end
|
13
11
|
|
14
12
|
subject(:repr_set) { described_class.new([foo_repr, bar_repr]) }
|
@@ -41,25 +39,25 @@ describe HalClient::RepresentationSet do
|
|
41
39
|
describe "#related" do
|
42
40
|
context "single target in each member" do
|
43
41
|
subject(:returned_val) { repr_set.related("spouse") }
|
44
|
-
it {
|
45
|
-
it {
|
46
|
-
it {
|
42
|
+
it { is_expected.to include_representation_of "http://example.com/foo-spouse" }
|
43
|
+
it { is_expected.to include_representation_of "http://example.com/bar-spouse" }
|
44
|
+
it { is_expected.to have(2).items }
|
47
45
|
end
|
48
46
|
|
49
47
|
context "multiple targets" do
|
50
48
|
subject(:returned_val) { repr_set.related("sibling") }
|
51
|
-
it {
|
52
|
-
it {
|
53
|
-
it {
|
54
|
-
it {
|
49
|
+
it { is_expected.to include_representation_of "http://example.com/foo-brother" }
|
50
|
+
it { is_expected.to include_representation_of "http://example.com/foo-sister" }
|
51
|
+
it { is_expected.to include_representation_of "http://example.com/bar-brother" }
|
52
|
+
it { is_expected.to have(3).items }
|
55
53
|
end
|
56
54
|
|
57
55
|
context "templated" do
|
58
56
|
subject(:returned_val) { repr_set.related("cousin", distance: "first") }
|
59
|
-
it {
|
60
|
-
it {
|
61
|
-
it {
|
62
|
-
it {
|
57
|
+
it { is_expected.to include_representation_of "http://example.com/foo-first-cousin" }
|
58
|
+
it { is_expected.to include_representation_of "http://example.com/bar-paternal-first-cousin" }
|
59
|
+
it { is_expected.to include_representation_of "http://example.com/bar-maternal-first-cousin" }
|
60
|
+
it { is_expected.to have(3).items }
|
63
61
|
end
|
64
62
|
end
|
65
63
|
|
@@ -1,8 +1,6 @@
|
|
1
|
-
require_relative "../spec_helper"
|
2
|
-
|
3
1
|
require "hal_client/representation"
|
4
2
|
|
5
|
-
describe HalClient::Representation do
|
3
|
+
RSpec.describe HalClient::Representation do
|
6
4
|
let(:raw_repr) { <<-HAL }
|
7
5
|
{ "prop1": 1
|
8
6
|
,"prop2": 2
|
@@ -176,12 +174,12 @@ HAL
|
|
176
174
|
describe "#fetch" do
|
177
175
|
context "for existent property" do
|
178
176
|
subject { repr.fetch "prop1" }
|
179
|
-
it {
|
177
|
+
it { is_expected.to eq 1 }
|
180
178
|
end
|
181
179
|
|
182
180
|
context "for existent link" do
|
183
181
|
subject { repr.fetch "link1" }
|
184
|
-
it {
|
182
|
+
it { is_expected.to have(1).item }
|
185
183
|
it "includes related resource representation" do
|
186
184
|
expect(subject.first.href).to eq "http://example.com/bar"
|
187
185
|
end
|
@@ -189,7 +187,7 @@ HAL
|
|
189
187
|
|
190
188
|
context "for existent embedded" do
|
191
189
|
subject { repr.fetch "embed1" }
|
192
|
-
it {
|
190
|
+
it { is_expected.to have(1).item }
|
193
191
|
it "includes related resource representation" do
|
194
192
|
expect(subject.first.href).to eq "http://example.com/baz"
|
195
193
|
end
|
@@ -203,63 +201,63 @@ HAL
|
|
203
201
|
|
204
202
|
context "non-existent item w/ default value" do
|
205
203
|
subject { repr.fetch "wat", "whatevs" }
|
206
|
-
it {
|
204
|
+
it { is_expected.to eq "whatevs" }
|
207
205
|
end
|
208
206
|
|
209
207
|
context "non-existent item w/ default value generator" do
|
210
208
|
subject { repr.fetch("wat"){|key| key+"gen" } }
|
211
|
-
it {
|
209
|
+
it { is_expected.to eq "watgen" }
|
212
210
|
end
|
213
211
|
end
|
214
212
|
|
215
213
|
describe "#[]" do
|
216
214
|
context "for existent property" do
|
217
215
|
subject { repr["prop1"] }
|
218
|
-
it {
|
216
|
+
it { is_expected.to eq 1 }
|
219
217
|
end
|
220
218
|
|
221
219
|
context "for existent link" do
|
222
220
|
subject { repr["link1"] }
|
223
|
-
it {
|
224
|
-
it {
|
221
|
+
it { is_expected.to have(1).item }
|
222
|
+
it { is_expected.to include_representation_of "http://example.com/bar" }
|
225
223
|
end
|
226
224
|
|
227
225
|
context "for existent embedded" do
|
228
226
|
subject { repr["embed1"] }
|
229
|
-
it {
|
230
|
-
it {
|
227
|
+
it { is_expected.to have(1).item }
|
228
|
+
it { is_expected.to include_representation_of "http://example.com/baz" }
|
231
229
|
end
|
232
230
|
|
233
231
|
context "non-existent item w/o default" do
|
234
232
|
subject { repr["wat"] }
|
235
|
-
it {
|
233
|
+
it { is_expected.to be_nil }
|
236
234
|
end
|
237
235
|
end
|
238
236
|
|
239
237
|
describe "#related" do
|
240
238
|
context "for existent link" do
|
241
239
|
subject { repr.related "link1" }
|
242
|
-
it {
|
243
|
-
it {
|
240
|
+
it { is_expected.to have(1).item }
|
241
|
+
it { is_expected.to include_representation_of "http://example.com/bar" }
|
244
242
|
end
|
245
243
|
|
246
244
|
context "for existent compound link" do
|
247
245
|
subject { repr.related "link3" }
|
248
|
-
it {
|
249
|
-
it {
|
250
|
-
it {
|
246
|
+
it { is_expected.to have(2).item }
|
247
|
+
it { is_expected.to include_representation_of "http://example.com/link3-a" }
|
248
|
+
it { is_expected.to include_representation_of "http://example.com/link3-b" }
|
251
249
|
end
|
252
250
|
|
253
251
|
context "for existent templated link" do
|
254
252
|
subject { repr.related "templated", name: "bob" }
|
255
|
-
it {
|
256
|
-
it {
|
253
|
+
it { is_expected.to have(1).item }
|
254
|
+
it { is_expected.to include_representation_of "http://example.com/people?name=bob" }
|
257
255
|
end
|
258
256
|
|
259
257
|
context "for existent embedded" do
|
260
258
|
subject { repr.related "embed1" }
|
261
|
-
it {
|
262
|
-
it {
|
259
|
+
it { is_expected.to have(1).item }
|
260
|
+
it { is_expected.to include_representation_of "http://example.com/baz" }
|
263
261
|
end
|
264
262
|
|
265
263
|
context "non-existent item w/o default" do
|
@@ -319,17 +317,17 @@ HAL
|
|
319
317
|
|
320
318
|
describe "#related return value" do
|
321
319
|
subject(:return_val) { repr.related("http://example.com/rels/bar") }
|
322
|
-
it {
|
320
|
+
it { is_expected.to include_representation_of "http://example.com/bar" }
|
323
321
|
end
|
324
322
|
|
325
323
|
describe "#[] return value" do
|
326
324
|
subject(:return_val) { repr["http://example.com/rels/bar"] }
|
327
|
-
it {
|
325
|
+
it { is_expected.to include_representation_of "http://example.com/bar" }
|
328
326
|
end
|
329
327
|
|
330
328
|
describe "#related_hrefs return value" do
|
331
329
|
subject(:return_val) { repr.related_hrefs("http://example.com/rels/bar") }
|
332
|
-
it {
|
330
|
+
it { is_expected.to include "http://example.com/bar" }
|
333
331
|
end
|
334
332
|
end
|
335
333
|
|
@@ -347,17 +345,17 @@ HAL
|
|
347
345
|
|
348
346
|
describe "#related return value " do
|
349
347
|
subject(:return_val) { repr.related("http://example.com/rels/embed1") }
|
350
|
-
it {
|
348
|
+
it { is_expected.to include_representation_of "http://example.com/embed1" }
|
351
349
|
end
|
352
350
|
|
353
351
|
describe "#[] return value " do
|
354
352
|
subject(:return_val) { repr["http://example.com/rels/embed1"] }
|
355
|
-
it {
|
353
|
+
it { is_expected.to include_representation_of "http://example.com/embed1" }
|
356
354
|
end
|
357
355
|
|
358
356
|
describe "#related_hrefs return value " do
|
359
357
|
subject(:return_val) { repr.related_hrefs("http://example.com/rels/embed1") }
|
360
|
-
it {
|
358
|
+
it { is_expected.to include "http://example.com/embed1" }
|
361
359
|
end
|
362
360
|
end
|
363
361
|
|
@@ -409,8 +407,8 @@ HAL
|
|
409
407
|
end
|
410
408
|
|
411
409
|
context "non-collection" do
|
412
|
-
specify { expect{repr.as_enum}.to raise_error }
|
413
|
-
specify { expect{repr.to_enum}.to raise_error }
|
410
|
+
specify { expect{repr.as_enum}.to raise_error(HalClient::NotACollectionError) }
|
411
|
+
specify { expect{repr.to_enum}.to raise_error(HalClient::NotACollectionError) }
|
414
412
|
end
|
415
413
|
|
416
414
|
# Background
|
@@ -473,7 +471,7 @@ HAL
|
|
473
471
|
|
474
472
|
end
|
475
473
|
|
476
|
-
describe HalClient::Representation, "w/o hal_client" do
|
474
|
+
RSpec.describe HalClient::Representation, "w/o hal_client" do
|
477
475
|
subject(:repr) { described_class.new(parsed_json: MultiJson.load(raw_repr)) }
|
478
476
|
|
479
477
|
specify { expect(subject.href).to eq "http://example.com/foo" }
|
data/spec/hal_client_spec.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
|
-
require_relative "./spec_helper"
|
2
1
|
require "hal_client"
|
2
|
+
require 'http'
|
3
3
|
|
4
|
-
describe HalClient do
|
4
|
+
RSpec.describe HalClient do
|
5
5
|
describe ".new()" do
|
6
6
|
subject { HalClient.new }
|
7
|
-
it {
|
7
|
+
it { is_expected.to be_kind_of HalClient }
|
8
8
|
end
|
9
9
|
|
10
10
|
subject(:client) { HalClient.new }
|
11
11
|
|
12
12
|
describe '.new w/ custom accept' do
|
13
13
|
subject { HalClient.new(accept: "application/vnd.myspecialmediatype") }
|
14
|
-
it {
|
14
|
+
it { is_expected.to be_kind_of HalClient }
|
15
15
|
end
|
16
16
|
|
17
17
|
describe "#get(<url>)" do
|
@@ -24,7 +24,7 @@ describe HalClient do
|
|
24
24
|
|
25
25
|
describe "request" do
|
26
26
|
subject { request }
|
27
|
-
it("should have been made") {
|
27
|
+
it("should have been made") { is_expected.to have_been_made }
|
28
28
|
|
29
29
|
it "sends accept header" do
|
30
30
|
expect(request.with(headers: {'Accept' => /application\/hal\+json/i})).
|
@@ -87,6 +87,43 @@ describe HalClient do
|
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
90
|
+
context "client reuse" do
|
91
|
+
let(:return_val) { nil }
|
92
|
+
let(:base_client) { instance_double('HTTP::Client') }
|
93
|
+
let(:real_client) { HTTP::Client.new }
|
94
|
+
subject(:client) { HalClient.new(base_client: base_client) }
|
95
|
+
|
96
|
+
it 'creates a base client with headers' do
|
97
|
+
expect(base_client).to receive(:with_headers) do |headers|
|
98
|
+
expect(headers.to_h).to include('Accept' => 'application/hal+json;q=0')
|
99
|
+
|
100
|
+
real_client
|
101
|
+
end
|
102
|
+
|
103
|
+
client.get "http://example.com/foo"
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'reuses base client with headers instances' do
|
107
|
+
expect(base_client).to receive(:with_headers) do |headers|
|
108
|
+
expect(headers.to_h).to include('Accept' => 'application/hal+json;q=0', 'Foo' => 'Bar')
|
109
|
+
|
110
|
+
real_client
|
111
|
+
end.once
|
112
|
+
|
113
|
+
client.get("http://example.com/foo", 'Foo' => 'Bar')
|
114
|
+
|
115
|
+
expect(base_client).to receive(:with_headers) do |headers|
|
116
|
+
expect(headers.to_h).to include('Accept' => 'application/hal+json;q=0', 'Hello' => 'World')
|
117
|
+
|
118
|
+
real_client
|
119
|
+
end.once
|
120
|
+
|
121
|
+
client.get("http://example.com/foo", 'Hello' => 'World')
|
122
|
+
|
123
|
+
client.get("http://example.com/foo", 'Foo' => 'Bar')
|
124
|
+
client.get("http://example.com/foo", 'Hello' => 'World')
|
125
|
+
end
|
126
|
+
end
|
90
127
|
end
|
91
128
|
|
92
129
|
context "server takes too long" do
|
@@ -173,7 +210,7 @@ describe HalClient do
|
|
173
210
|
|
174
211
|
describe "request" do
|
175
212
|
subject { request }
|
176
|
-
it("should have been made") {
|
213
|
+
it("should have been made") { is_expected.to have_been_made }
|
177
214
|
|
178
215
|
it "sends accept header" do
|
179
216
|
expect(request.with(headers: {'Accept' => /application\/hal\+json/})).
|
@@ -211,7 +248,7 @@ describe HalClient do
|
|
211
248
|
describe "request" do
|
212
249
|
before do return_val end
|
213
250
|
subject { post_request }
|
214
|
-
it("should have been made") {
|
251
|
+
it("should have been made") { is_expected.to have_been_made }
|
215
252
|
|
216
253
|
it "sends content type header" do
|
217
254
|
expect(post_request.with(headers: {'Content-Type' => 'application/hal+json'})).
|
@@ -223,7 +260,7 @@ describe HalClient do
|
|
223
260
|
let(:return_val) { client.post url, post_data, "Content-Type" => "text/plain" }
|
224
261
|
before do return_val end
|
225
262
|
subject { post_request }
|
226
|
-
it("should have been made") {
|
263
|
+
it("should have been made") { is_expected.to have_been_made }
|
227
264
|
|
228
265
|
it "sends content type header" do
|
229
266
|
expect(post_request.with(headers: {'Content-Type' => 'text/plain'})).
|
@@ -280,6 +317,43 @@ describe HalClient do
|
|
280
317
|
expect(logger.info_entries.first).to include "http://example.com/foo"
|
281
318
|
end
|
282
319
|
end
|
320
|
+
|
321
|
+
context "client reuse" do
|
322
|
+
let(:base_client) { instance_double('HTTP::Client') }
|
323
|
+
let(:real_client) { HTTP::Client.new }
|
324
|
+
subject(:client) { HalClient.new(base_client: base_client) }
|
325
|
+
|
326
|
+
it 'creates a base client with headers' do
|
327
|
+
expect(base_client).to receive(:with_headers) do |headers|
|
328
|
+
expect(headers.to_h).to include('Accept' => 'application/hal+json;q=0')
|
329
|
+
|
330
|
+
real_client
|
331
|
+
end
|
332
|
+
|
333
|
+
client.post(url, post_data)
|
334
|
+
end
|
335
|
+
|
336
|
+
it 'reuses base client with headers instances' do
|
337
|
+
expect(base_client).to receive(:with_headers) do |headers|
|
338
|
+
expect(headers.to_h).to include('Accept' => 'application/hal+json;q=0', 'Foo' => 'Bar')
|
339
|
+
|
340
|
+
real_client
|
341
|
+
end.once
|
342
|
+
|
343
|
+
client.post(url, post_data, 'Foo' => 'Bar')
|
344
|
+
|
345
|
+
expect(base_client).to receive(:with_headers) do |headers|
|
346
|
+
expect(headers.to_h).to include('Accept' => 'application/hal+json;q=0', 'Hello' => 'World')
|
347
|
+
|
348
|
+
real_client
|
349
|
+
end.once
|
350
|
+
|
351
|
+
client.post(url, post_data, 'Hello' => 'World')
|
352
|
+
|
353
|
+
client.post(url, post_data, 'Foo' => 'Bar')
|
354
|
+
client.post(url, post_data, 'Hello' => 'World')
|
355
|
+
end
|
356
|
+
end
|
283
357
|
end
|
284
358
|
|
285
359
|
describe ".post(<url>)" do
|
@@ -291,7 +365,7 @@ describe HalClient do
|
|
291
365
|
|
292
366
|
describe "request" do
|
293
367
|
subject { post_request }
|
294
|
-
it("should have been made") {
|
368
|
+
it("should have been made") { is_expected.to have_been_made }
|
295
369
|
|
296
370
|
it "sends accept header" do
|
297
371
|
expect(post_request.with(headers: {'Content-Type' => 'application/hal+json'})).
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,78 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command.
|
2
|
+
#
|
3
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
4
|
+
RSpec.configure do |config|
|
5
|
+
config.expect_with :rspec do |expectations|
|
6
|
+
# This option will default to `true` in RSpec 4.
|
7
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
8
|
+
end
|
9
|
+
|
10
|
+
config.mock_with :rspec do |mocks|
|
11
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
12
|
+
# a real object. This is generally recommended, and will default to
|
13
|
+
# `true` in RSpec 4.
|
14
|
+
mocks.verify_partial_doubles = true
|
15
|
+
end
|
16
|
+
|
17
|
+
# This option will default to `:apply_to_host_groups` in RSpec 4 (and will
|
18
|
+
# have no way to turn it off -- the option exists only for backwards
|
19
|
+
# compatibility in RSpec 3). It causes shared context metadata to be
|
20
|
+
# inherited by the metadata hash of host groups and examples, rather than
|
21
|
+
# triggering implicit auto-inclusion in groups with matching metadata.
|
22
|
+
config.shared_context_metadata_behavior = :apply_to_host_groups
|
23
|
+
|
24
|
+
# This allows you to limit a spec run to individual examples or groups
|
25
|
+
# you care about by tagging them with `:focus` metadata. When nothing
|
26
|
+
# is tagged with `:focus`, all examples get run. RSpec also provides
|
27
|
+
# aliases for `it`, `describe`, and `context` that include `:focus`
|
28
|
+
# metadata: `fit`, `fdescribe` and `fcontext`, respectively.
|
29
|
+
config.filter_run_when_matching :focus
|
30
|
+
|
31
|
+
# Allows RSpec to persist some state between runs in order to support
|
32
|
+
# the `--only-failures` and `--next-failure` CLI options. We recommend
|
33
|
+
# you configure your source control system to ignore this file.
|
34
|
+
config.example_status_persistence_file_path = "spec/examples.txt"
|
35
|
+
|
36
|
+
# Limits the available syntax to the non-monkey patched syntax that is
|
37
|
+
# recommended.
|
38
|
+
config.disable_monkey_patching!
|
39
|
+
|
40
|
+
# This setting enables warnings. It's recommended, but in some cases may
|
41
|
+
# be too noisy due to issues in dependencies.
|
42
|
+
config.warnings = true
|
43
|
+
|
44
|
+
# Many RSpec users commonly either run the entire suite or an individual
|
45
|
+
# file, and it's useful to allow more verbose output when running an
|
46
|
+
# individual spec file.
|
47
|
+
if config.files_to_run.one?
|
48
|
+
# Use the documentation formatter for detailed output,
|
49
|
+
# unless a formatter has already been configured
|
50
|
+
# (e.g. via a command-line flag).
|
51
|
+
config.default_formatter = 'doc'
|
52
|
+
end
|
53
|
+
|
54
|
+
# Print the n slowest examples and example groups at the
|
55
|
+
# end of the spec run, to help surface which specs are running
|
56
|
+
# particularly slow.
|
57
|
+
config.profile_examples = 5
|
58
|
+
|
59
|
+
# Run specs in random order to surface order dependencies. If you find an
|
60
|
+
# order dependency and want to debug it, you can fix the order by providing
|
61
|
+
# the seed, which is printed after each run.
|
62
|
+
# --seed 1234
|
63
|
+
config.order = :random
|
64
|
+
|
65
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
66
|
+
# Setting this allows you to use `--seed` to deterministically reproduce
|
67
|
+
# test failures related to randomization by passing the same `--seed` value
|
68
|
+
# as the one that triggered the failure.
|
69
|
+
Kernel.srand config.seed
|
70
|
+
end
|
71
|
+
|
72
|
+
# hal_client-specific additions
|
73
|
+
|
1
74
|
$LOAD_PATH << Pathname(__FILE__).dirname + "../lib"
|
2
75
|
|
3
|
-
require 'rspec'
|
4
76
|
require 'webmock/rspec'
|
5
77
|
require 'multi_json'
|
6
78
|
require 'rspec/collection_matchers'
|
@@ -9,4 +81,4 @@ require 'support/custom_matchers'
|
|
9
81
|
|
10
82
|
RSpec.configure do |config|
|
11
83
|
config.include CustomMatchers
|
12
|
-
end
|
84
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hal-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.17.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Williams
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-08
|
11
|
+
date: 2016-11-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: http
|
@@ -86,14 +86,14 @@ dependencies:
|
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 3.
|
89
|
+
version: '3.5'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: 3.
|
96
|
+
version: '3.5'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: webmock
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -128,6 +128,20 @@ dependencies:
|
|
128
128
|
- - ">="
|
129
129
|
- !ruby/object:Gem::Version
|
130
130
|
version: '0'
|
131
|
+
- !ruby/object:Gem::Dependency
|
132
|
+
name: pry
|
133
|
+
requirement: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
type: :development
|
139
|
+
prerelease: false
|
140
|
+
version_requirements: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
131
145
|
description: An easy to use interface for REST APIs that use HAL.
|
132
146
|
email:
|
133
147
|
- pezra@barelyenough.org
|
@@ -136,6 +150,7 @@ extensions: []
|
|
136
150
|
extra_rdoc_files: []
|
137
151
|
files:
|
138
152
|
- ".gitignore"
|
153
|
+
- ".rspec"
|
139
154
|
- ".travis.yml"
|
140
155
|
- Gemfile
|
141
156
|
- LICENSE.txt
|
@@ -198,4 +213,3 @@ test_files:
|
|
198
213
|
- spec/hal_client_spec.rb
|
199
214
|
- spec/spec_helper.rb
|
200
215
|
- spec/support/custom_matchers.rb
|
201
|
-
has_rdoc:
|