representors 0.0.5
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 +7 -0
- data/CHANGELOG.md +18 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +126 -0
- data/LICENSE.md +19 -0
- data/README.md +28 -0
- data/Rakefile +10 -0
- data/lib/representor_support/utilities.rb +39 -0
- data/lib/representors.rb +5 -0
- data/lib/representors/errors.rb +7 -0
- data/lib/representors/field.rb +108 -0
- data/lib/representors/options.rb +67 -0
- data/lib/representors/representor.rb +161 -0
- data/lib/representors/representor_builder.rb +64 -0
- data/lib/representors/representor_hash.rb +59 -0
- data/lib/representors/serialization.rb +4 -0
- data/lib/representors/serialization/deserializer_base.rb +29 -0
- data/lib/representors/serialization/deserializer_factory.rb +13 -0
- data/lib/representors/serialization/hal_deserializer.rb +44 -0
- data/lib/representors/serialization/hal_serializer.rb +91 -0
- data/lib/representors/serialization/hale_deserializer.rb +162 -0
- data/lib/representors/serialization/hale_serializer.rb +110 -0
- data/lib/representors/serialization/serialization_base.rb +27 -0
- data/lib/representors/serialization/serialization_factory_base.rb +54 -0
- data/lib/representors/serialization/serializer_base.rb +20 -0
- data/lib/representors/serialization/serializer_factory.rb +17 -0
- data/lib/representors/transition.rb +130 -0
- data/lib/representors/version.rb +4 -0
- data/spec/fixtures/complex_hal.json +92 -0
- data/spec/fixtures/complex_hale_document.json +81 -0
- data/spec/fixtures/drds_hash.rb +120 -0
- data/spec/fixtures/hale_spec_examples/basic.json +77 -0
- data/spec/fixtures/hale_spec_examples/complex_reference_objects.json +157 -0
- data/spec/fixtures/hale_spec_examples/data.json +17 -0
- data/spec/fixtures/hale_spec_examples/data_objects.json +96 -0
- data/spec/fixtures/hale_spec_examples/link_objects.json +18 -0
- data/spec/fixtures/hale_spec_examples/nested_ref.json +43 -0
- data/spec/fixtures/hale_spec_examples/reference_objects.json +89 -0
- data/spec/fixtures/hale_tutorial_examples/basic_links.json +85 -0
- data/spec/fixtures/hale_tutorial_examples/basic_links_with_orders.json +96 -0
- data/spec/fixtures/hale_tutorial_examples/basic_links_with_references.json +108 -0
- data/spec/fixtures/hale_tutorial_examples/embedded.json +182 -0
- data/spec/fixtures/hale_tutorial_examples/empty.json +1 -0
- data/spec/fixtures/hale_tutorial_examples/enctype.json +14 -0
- data/spec/fixtures/hale_tutorial_examples/final.json +141 -0
- data/spec/fixtures/hale_tutorial_examples/get_link.json +17 -0
- data/spec/fixtures/hale_tutorial_examples/get_link_with_data.json +29 -0
- data/spec/fixtures/hale_tutorial_examples/links.json +11 -0
- data/spec/fixtures/hale_tutorial_examples/links_only.json +3 -0
- data/spec/fixtures/hale_tutorial_examples/meta.json +208 -0
- data/spec/fixtures/hale_tutorial_examples/self_link.json +7 -0
- data/spec/fixtures/single_drd.rb +266 -0
- data/spec/lib/representors/complex_representor_spec.rb +288 -0
- data/spec/lib/representors/field_spec.rb +141 -0
- data/spec/lib/representors/representor_builder_spec.rb +223 -0
- data/spec/lib/representors/representor_spec.rb +285 -0
- data/spec/lib/representors/serialization/deserializer_factory_spec.rb +118 -0
- data/spec/lib/representors/serialization/hal_deserializer_spec.rb +34 -0
- data/spec/lib/representors/serialization/hal_serializer_spec.rb +171 -0
- data/spec/lib/representors/serialization/hale_deserializer_spec.rb +59 -0
- data/spec/lib/representors/serialization/hale_roundtrip_spec.rb +34 -0
- data/spec/lib/representors/serialization/hale_serializer_spec.rb +659 -0
- data/spec/lib/representors/serialization/serializer_factory_spec.rb +108 -0
- data/spec/lib/representors/transition_spec.rb +349 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/support/basic-hale.json +12 -0
- data/spec/support/hal_representor_shared.rb +206 -0
- data/spec/support/helpers.rb +8 -0
- data/tasks/benchmark.rake +75 -0
- data/tasks/complex_hal_document.json +98 -0
- data/tasks/test_specs.rake +37 -0
- data/tasks/yard.rake +22 -0
- metadata +232 -0
@@ -0,0 +1,285 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'yaml'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module Representors
|
6
|
+
describe Representor do
|
7
|
+
let(:base_doc) {'A list of DRDs.'}
|
8
|
+
let(:rel_first_transition) {'self'}
|
9
|
+
let(:rel_second_transition) {'search'}
|
10
|
+
before do
|
11
|
+
@base_representor = {
|
12
|
+
protocol: 'http',
|
13
|
+
href: 'www.example.com/drds',
|
14
|
+
id: 'drds',
|
15
|
+
doc: base_doc,
|
16
|
+
attributes: {},
|
17
|
+
embedded: {},
|
18
|
+
links: {},
|
19
|
+
transitions: []
|
20
|
+
}
|
21
|
+
|
22
|
+
@semantic_elements = {
|
23
|
+
attributes: {
|
24
|
+
total_count: {
|
25
|
+
doc: 'The total count of DRDs.',
|
26
|
+
type: 'semantic',
|
27
|
+
profile: 'http://alps.io/schema.org/Integer',
|
28
|
+
sample: 1,
|
29
|
+
value: 2
|
30
|
+
},
|
31
|
+
uptime: {
|
32
|
+
value: '76ms'
|
33
|
+
},
|
34
|
+
brackreference: {
|
35
|
+
value: 886396728
|
36
|
+
}
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
@transition_elements = {
|
41
|
+
transitions: [
|
42
|
+
{
|
43
|
+
doc: 'Returns a list of DRDs.',
|
44
|
+
rt: 'drds',
|
45
|
+
type: 'safe',
|
46
|
+
href: 'some.example.com/list',
|
47
|
+
rel: rel_first_transition
|
48
|
+
},
|
49
|
+
{
|
50
|
+
doc: 'Returns a list of DRDs that satisfy the search term.',
|
51
|
+
rt: 'drds',
|
52
|
+
type: 'safe',
|
53
|
+
href: '/',
|
54
|
+
rel: rel_second_transition,
|
55
|
+
descriptors: {
|
56
|
+
name: {
|
57
|
+
doc: "Name to search",
|
58
|
+
profile: "http://alps.io/schema.org/Text",
|
59
|
+
sample: "drdname",
|
60
|
+
options: {'list' => ['one', 'two']}
|
61
|
+
},
|
62
|
+
status: {
|
63
|
+
doc: "How is the DRD.",
|
64
|
+
profile: "http://alps.io/schema.org/Text",
|
65
|
+
sample: "renegade",
|
66
|
+
options: {'list' => ['renegade', 'compliant'], 'id' => 'status_list'}
|
67
|
+
}
|
68
|
+
}
|
69
|
+
}
|
70
|
+
]
|
71
|
+
}
|
72
|
+
end
|
73
|
+
let(:representor_hash) { @representor_hash || @base_representor }
|
74
|
+
let(:subject) { Representor.new(representor_hash) }
|
75
|
+
|
76
|
+
describe '.new' do
|
77
|
+
it 'returns a Representors::Representor instance' do
|
78
|
+
expect(subject).to be_an_instance_of(Representor)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'yields a builder' do
|
82
|
+
Representor.new do |builder|
|
83
|
+
expect(builder).to be_an_instance_of(RepresentorBuilder)
|
84
|
+
builder
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'returns a Representors::Representor instance with a nil argument' do
|
89
|
+
expect(Representor.new).to be_an_instance_of(Representor)
|
90
|
+
end
|
91
|
+
|
92
|
+
describe '#to_s' do
|
93
|
+
it 'retuns a string representation' do
|
94
|
+
expect(eval(subject.to_s)).to eq(representor_hash)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe '#doc' do
|
99
|
+
context 'the hash has a doc' do
|
100
|
+
let(:doc) {base_doc}
|
101
|
+
it 'returns the same value specified under the doc element of the hash' do
|
102
|
+
@representor_hash = RepresentorHash.new
|
103
|
+
@representor_hash.doc = doc
|
104
|
+
expect(subject.doc).to eq(doc)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
context 'the hash has non doc' do
|
108
|
+
it 'returns an empty string' do
|
109
|
+
@representor_hash = RepresentorHash.new
|
110
|
+
expect(subject.doc).to eq('')
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe '#identifier' do
|
116
|
+
context 'href and protocol are specified' do
|
117
|
+
let(:href) { 'www.example.com/drds'}
|
118
|
+
let(:protocol) {'http'}
|
119
|
+
it 'returns an url' do
|
120
|
+
@representor_hash = RepresentorHash.new(protocol: protocol, href: href)
|
121
|
+
expect(subject.identifier).to match(URI::regexp)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context 'href is not specified and protocol is specified' do
|
126
|
+
let(:protocol) {'http'}
|
127
|
+
it 'returns an url with object id' do
|
128
|
+
@representor_hash = RepresentorHash.new(protocol: protocol)
|
129
|
+
expect(subject.identifier).to eq('http://%s' % subject.object_id)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context 'href is specified and protocol is not specified' do
|
134
|
+
let(:href) { 'www.example.com/drds'}
|
135
|
+
it 'returns an url with default protocol' do
|
136
|
+
@representor_hash = RepresentorHash.new(href: href)
|
137
|
+
expect(subject.identifier).to eq('http://%s' % href)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
context 'href is not specified and protocol is not specified' do
|
142
|
+
let(:href) { 'www.example.com/drds'}
|
143
|
+
it 'returns an unknown protocol object url' do
|
144
|
+
@representor_hash = RepresentorHash.new
|
145
|
+
expect(subject.identifier).to eq("ruby_id://%s" % subject.object_id)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
describe '#to_hash' do
|
152
|
+
it 'returns a hash that it can be reconstructed with' do
|
153
|
+
expect(Representor.new(subject.to_hash).to_hash).to eq(@base_representor)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
describe '#to_yaml' do
|
158
|
+
it 'returns a yaml file that represents its internal hash' do
|
159
|
+
expect(YAML.load(subject.to_yaml)).to eq(@base_representor)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe '#properties' do
|
164
|
+
it 'returns a hash of attributes associated with the represented resource' do
|
165
|
+
@representor_hash = @base_representor.merge(@semantic_elements)
|
166
|
+
semantic_elements_present = %w(total_count uptime brackreference).all? do |key|
|
167
|
+
subject.properties[key.to_sym] == @semantic_elements[:attributes][key.to_sym][:value]
|
168
|
+
end
|
169
|
+
expect(semantic_elements_present).to eq(true)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe '#embedded' do
|
174
|
+
let(:embedded_resource) {'embedded_resource'}
|
175
|
+
let(:profile_link) { {profile: "http://alps.io/schema.org/Thing"} }
|
176
|
+
|
177
|
+
before do
|
178
|
+
@count = 3
|
179
|
+
@representor_hash = RepresentorHash.new(@base_representor).merge(@semantic_elements)
|
180
|
+
embedded_resources = []
|
181
|
+
|
182
|
+
@transitions_hash = {
|
183
|
+
transitions: [
|
184
|
+
{ doc: 'Returns a list of DRDs',
|
185
|
+
type: 'safe',
|
186
|
+
rel: 'self'
|
187
|
+
}
|
188
|
+
]
|
189
|
+
}
|
190
|
+
|
191
|
+
@count.times do |i|
|
192
|
+
transitions_hash = deep_dup(@transitions_hash)
|
193
|
+
transitions_hash[:transitions][0][:href] = "some.example.com/list/#{i}"
|
194
|
+
embedded_item = deep_dup(@representor_hash).merge(transitions_hash)
|
195
|
+
embedded_item[:links] = profile_link if i == 0
|
196
|
+
embedded_resources << embedded_item
|
197
|
+
end
|
198
|
+
|
199
|
+
|
200
|
+
@representor_hash[:embedded] = { embedded_resource => embedded_resources }
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'returns a set of Representor objects' do
|
204
|
+
expect(subject.embedded[embedded_resource].first).to be_an_instance_of(Representors::Representor)
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'returns a Representor objects that has its data' do
|
208
|
+
embedded_objects_valid = subject.embedded[embedded_resource].all? { |embed| embed.doc == base_doc }
|
209
|
+
expect(embedded_objects_valid).to eq(true)
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'returns the all the Representors' do
|
213
|
+
expect(subject.embedded[embedded_resource].count).to eq(@count)
|
214
|
+
end
|
215
|
+
|
216
|
+
it 'doesn\'t blow up even if nothing is embedded' do
|
217
|
+
@representor_hash = @base_representor
|
218
|
+
expect(subject.embedded.count).to eq(0)
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'includes appropriate profile links if it exists' do
|
222
|
+
expect(subject.transitions.first[:profile]).to eq(profile_link["profile"])
|
223
|
+
expect(subject.transitions[1][:profile]).to be_nil
|
224
|
+
expect(subject.transitions.last[:profile]).to be_nil
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
describe '#transitions' do
|
229
|
+
it 'returns all transitions' do
|
230
|
+
@representor_hash = @base_representor.merge(@transition_elements)
|
231
|
+
expect(subject.transitions.size).to eq(2)
|
232
|
+
has_transitions = subject.transitions.all? { |trans| trans.instance_of?(Transition) }
|
233
|
+
expect(has_transitions).to eq(true)
|
234
|
+
expect(subject.transitions[0].rel).to eq(rel_first_transition)
|
235
|
+
expect(subject.transitions[1].rel).to eq(rel_second_transition)
|
236
|
+
end
|
237
|
+
context 'with transitions which have the same rel and href' do
|
238
|
+
it 'returns only one transition' do
|
239
|
+
transitions = { transitions: [
|
240
|
+
{
|
241
|
+
doc: 'Returns a list of DRDs.',
|
242
|
+
rt: 'drds',
|
243
|
+
type: 'safe',
|
244
|
+
href: 'some.example.com/list',
|
245
|
+
rel: rel_first_transition
|
246
|
+
},
|
247
|
+
{
|
248
|
+
doc: 'Returns a list of trusmis.',
|
249
|
+
rt: 'trusmis',
|
250
|
+
type: 'unsafe',
|
251
|
+
href: 'some.example.com/list',
|
252
|
+
rel: rel_first_transition
|
253
|
+
}
|
254
|
+
]
|
255
|
+
}
|
256
|
+
@representor_hash = @base_representor.merge(transitions)
|
257
|
+
expect(subject.transitions.size).to eq(1)
|
258
|
+
has_transitions = subject.transitions.all? { |trans| trans.instance_of?(Transition) }
|
259
|
+
expect(has_transitions).to eq(true)
|
260
|
+
expect(subject.transitions[0].rel).to eq(rel_first_transition)
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
describe '#meta_links' do
|
266
|
+
it 'should return a list of transitions representing those links' do
|
267
|
+
@base_representor[:links] = {
|
268
|
+
self: 'DRDs#drds/create',
|
269
|
+
help: 'Forms/create'
|
270
|
+
}
|
271
|
+
expect(subject.meta_links.size).to eq(2)
|
272
|
+
has_meta_link = subject.meta_links.all? { |trans| trans.instance_of?(Transition) }
|
273
|
+
expect(has_meta_link).to eq(true)
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
describe '#datalists' do
|
278
|
+
it 'returns all paramters and attributes that are members of a datalist' do
|
279
|
+
@representor_hash = @base_representor.merge(@transition_elements)
|
280
|
+
has_data_list = expect(subject.datalists.first.to_hash).to eq({"renegade" => "renegade", "compliant" => "compliant"})
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'representors/serialization/deserializer_factory'
|
3
|
+
|
4
|
+
module Representors
|
5
|
+
describe DeserializerFactory do
|
6
|
+
let(:factory) { Class.new(DeserializerFactory) } # prevent singleton pollution from spec
|
7
|
+
|
8
|
+
describe '.register_deserializers' do
|
9
|
+
it 'adds classes to the registered deserializers' do
|
10
|
+
serializer_classes = [double('deserializer1'), double('deserializer2')]
|
11
|
+
factory.register_deserializers(*serializer_classes)
|
12
|
+
|
13
|
+
expect(factory.registered_deserializers).to include(*serializer_classes)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '.registered_deserializers' do
|
18
|
+
before do
|
19
|
+
@deserializer_class = double('deserializer3')
|
20
|
+
factory.register_deserializers(@deserializer_class)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'memoizes' do
|
24
|
+
registered_deserializers = factory.registered_deserializers.object_id
|
25
|
+
|
26
|
+
expect(registered_deserializers).to eq(factory.registered_deserializers.object_id)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'returns a frozen list of registered_deserializers' do
|
30
|
+
expect(factory.registered_deserializers).to be_frozen
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'returns registered serializers' do
|
34
|
+
expect(factory.registered_deserializers).to include(@deserializer_class)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#build' do
|
39
|
+
let(:document) { {}.to_json }
|
40
|
+
subject(:deserializer) { DeserializerFactory.build(media_type, document) }
|
41
|
+
|
42
|
+
shared_examples_for 'a built deserializer' do
|
43
|
+
it 'sets the correct target in the deserializer' do
|
44
|
+
expect(deserializer.to_representor_hash).to eq(RepresentorHash.new)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
shared_examples_for 'a hal deserializer' do
|
49
|
+
it 'returns a HalDeserializer' do
|
50
|
+
expect(deserializer).to be_instance_of HalDeserializer
|
51
|
+
end
|
52
|
+
|
53
|
+
it_behaves_like 'a built deserializer'
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'with an empty response body' do
|
57
|
+
[nil, '', '{}', ' '].each do |response_body|
|
58
|
+
context "when given a #{response_body.inspect}" do
|
59
|
+
let(:media_type) { 'application/hal+json' }
|
60
|
+
let(:document) { '' }
|
61
|
+
|
62
|
+
it_behaves_like 'a hal deserializer'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'with hal+json media type as a string' do
|
68
|
+
let(:media_type) { 'application/hal+json' }
|
69
|
+
|
70
|
+
it_behaves_like 'a hal deserializer'
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'with hal+json media type as a symbol' do
|
74
|
+
let(:media_type) { :hal }
|
75
|
+
|
76
|
+
it_behaves_like 'a hal deserializer'
|
77
|
+
end
|
78
|
+
|
79
|
+
shared_examples_for 'a hale deserializer' do
|
80
|
+
it 'returns a HaleDeserializer' do
|
81
|
+
expect(deserializer).to be_instance_of HaleDeserializer
|
82
|
+
end
|
83
|
+
|
84
|
+
it_behaves_like 'a built deserializer'
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'with hale+json media type as a string' do
|
88
|
+
let(:media_type) { 'application/vnd.hale+json' }
|
89
|
+
|
90
|
+
it_behaves_like 'a hale deserializer'
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'with hale+json media type as a symbol' do
|
94
|
+
let(:media_type) { :hale }
|
95
|
+
|
96
|
+
it_behaves_like 'a hale deserializer'
|
97
|
+
end
|
98
|
+
|
99
|
+
shared_examples_for 'an unknown media type' do
|
100
|
+
it 'raises an unknown media type error' do
|
101
|
+
expect { deserializer }.to raise_error(UnknownMediaTypeError, "Unknown media-type: #{media_type}.")
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context 'unknown media type string' do
|
106
|
+
let(:media_type) { 'unknown' }
|
107
|
+
|
108
|
+
it_behaves_like 'an unknown media type'
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'unknown media type symbol' do
|
112
|
+
let(:media_type) { :unknown }
|
113
|
+
|
114
|
+
it_behaves_like 'an unknown media type'
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Representors::HalDeserializer do
|
4
|
+
|
5
|
+
it "initializes with a JSON document" do
|
6
|
+
expect(Representors::HalDeserializer.new({}.to_json)).to be_instance_of(Representors::HalDeserializer)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'provides the media-type application/vnd.hal+json' do
|
10
|
+
formats = Representors::HalDeserializer.media_types
|
11
|
+
expect(formats).to include('application/hal+json', 'application/json')
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'provides the media symbol :hal' do
|
15
|
+
expect(Representors::HalDeserializer.media_symbols).to include(:hal)
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#to_representor" do
|
19
|
+
it_behaves_like 'can create a representor from a hal document' do
|
20
|
+
subject(:deserializer) {Representors::HalDeserializer.new(document)}
|
21
|
+
end
|
22
|
+
|
23
|
+
context "when the Hal deserializer recieves a Hale document" do
|
24
|
+
it "deserializes as a Hal document and not a Hale document" do
|
25
|
+
file = File.read("#{SPEC_DIR}/fixtures/hale_tutorial_examples/meta.json")
|
26
|
+
hal_rep = Representors::HalDeserializer.new(file).to_representor
|
27
|
+
place_order_link_data = hal_rep.transitions.find { |t| t[:rel] == "place_order" }
|
28
|
+
expect(hal_rep.properties.keys).to include('_meta')
|
29
|
+
expect(place_order_link_data.interface_method).to eq('GET')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'yaml'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module Representors
|
6
|
+
describe Serialization::HalSerializer do
|
7
|
+
|
8
|
+
subject(:serializer) { SerializerFactory.build(:hal_json, Representor.new(document)) }
|
9
|
+
let(:result) {JSON.parse(serializer.to_media_type)}
|
10
|
+
let(:base_representor) do
|
11
|
+
{
|
12
|
+
protocol: 'http',
|
13
|
+
href: 'www.example.com/drds',
|
14
|
+
id: 'drds',
|
15
|
+
doc: 'doc'
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
shared_examples 'a hal documents attributes' do |representor_hash|
|
20
|
+
let(:document) { representor_hash.merge(base_representor) }
|
21
|
+
|
22
|
+
representor_hash[:attributes].each do |k, v|
|
23
|
+
it "includes the document attribute #{k} and associated value" do
|
24
|
+
expect(result[k]).to eq(v[:value])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
shared_examples 'a hal documents links' do |representor_hash|
|
30
|
+
let(:document) { representor_hash.merge(base_representor) }
|
31
|
+
|
32
|
+
representor_hash[:transitions].each do |item|
|
33
|
+
it "includes the document transition #{item}" do
|
34
|
+
links = result['_links']
|
35
|
+
link = links[item[:rel]]
|
36
|
+
expect(link['href']).to eq(item[:href])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
shared_examples 'a hal documents embedded hal documents' do |representor_hash|
|
42
|
+
let(:document) { representor_hash.merge(base_representor) }
|
43
|
+
|
44
|
+
representor_hash[:embedded].each do |embed_name, embed|
|
45
|
+
embed[:attributes].each do |k, v|
|
46
|
+
it "includes the document attribute #{k} and associated value" do
|
47
|
+
expect(result['_embedded'][embed_name][k]).to eq(v[:value])
|
48
|
+
end
|
49
|
+
end
|
50
|
+
embed[:transitions].each do |item|
|
51
|
+
it "includes the document attribute #{item} and associated value" do
|
52
|
+
expect(result['_embedded'][embed_name]['_links'][item[:rel]]['href']).to eq(item[:href])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
shared_examples 'a hal documents embedded collection' do |representor_hash|
|
59
|
+
let(:document) { representor_hash.merge(base_representor) }
|
60
|
+
|
61
|
+
representor_hash[:embedded].each do |embed_name, embeds|
|
62
|
+
embeds.each_with_index do |embed, index|
|
63
|
+
embed[:attributes].each do |k, v|
|
64
|
+
it "includes the document attribute #{k} and associated value" do
|
65
|
+
expect(result['_embedded'][embed_name][index][k]).to eq(v[:value])
|
66
|
+
end
|
67
|
+
end
|
68
|
+
embed[:transitions].each do |item|
|
69
|
+
it "includes the document attribute #{item} and associated value" do
|
70
|
+
expect(result['_embedded'][embed_name][index]['_links'][item[:rel]]['href']).to eq(item[:href])
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '#as_media_type' do
|
78
|
+
context 'empty document' do
|
79
|
+
let(:document) { {} }
|
80
|
+
|
81
|
+
it 'returns a hash with no attributes, links or embedded resources' do
|
82
|
+
empty_json_document = '{}'
|
83
|
+
expect(serializer.to_media_type).to eq(empty_json_document)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'Document with only properties' do
|
88
|
+
representor_hash = begin
|
89
|
+
{
|
90
|
+
attributes: {
|
91
|
+
'title' => {value: 'The Neverending Story'},
|
92
|
+
'author' => {value: 'Michael Ende'},
|
93
|
+
'pages' => {value: '396'}
|
94
|
+
}
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
it_behaves_like 'a hal documents attributes', representor_hash
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'Document with properties and links' do
|
102
|
+
representor_hash = begin
|
103
|
+
{
|
104
|
+
attributes: {
|
105
|
+
'title' => {value: 'The Neverending Story'},
|
106
|
+
},
|
107
|
+
transitions: [
|
108
|
+
{
|
109
|
+
href: '/mike',
|
110
|
+
rel: 'author',
|
111
|
+
}
|
112
|
+
]
|
113
|
+
}
|
114
|
+
end
|
115
|
+
|
116
|
+
it_behaves_like 'a hal documents attributes', representor_hash
|
117
|
+
it_behaves_like 'a hal documents links', representor_hash
|
118
|
+
end
|
119
|
+
|
120
|
+
context 'Document with properties, links, and embedded' do
|
121
|
+
representor_hash = begin
|
122
|
+
{
|
123
|
+
attributes: {
|
124
|
+
'title' => {value: 'The Neverending Story'},
|
125
|
+
},
|
126
|
+
transitions: [
|
127
|
+
{
|
128
|
+
href: '/mike',
|
129
|
+
rel: 'author',
|
130
|
+
}
|
131
|
+
],
|
132
|
+
embedded: {
|
133
|
+
'embedded_book' => {attributes: {'content' => { value: 'A...' } }, transitions: [{rel: 'self', href: '/foo'}]}
|
134
|
+
}
|
135
|
+
}
|
136
|
+
end
|
137
|
+
|
138
|
+
it_behaves_like 'a hal documents attributes', representor_hash
|
139
|
+
it_behaves_like 'a hal documents links', representor_hash
|
140
|
+
it_behaves_like 'a hal documents embedded hal documents', representor_hash
|
141
|
+
end
|
142
|
+
|
143
|
+
context 'Document with an embedded collection' do
|
144
|
+
representor_hash = begin
|
145
|
+
{
|
146
|
+
attributes: {
|
147
|
+
'title' => {value: 'The Neverending Story'},
|
148
|
+
},
|
149
|
+
transitions: [
|
150
|
+
{
|
151
|
+
href: '/mike',
|
152
|
+
rel: 'author',
|
153
|
+
}
|
154
|
+
],
|
155
|
+
embedded: {
|
156
|
+
'embedded_book' => [
|
157
|
+
{attributes: {'content' => { value: 'A...' } }, transitions: [{rel: 'self', href: '/foo1'}]},
|
158
|
+
{attributes: {'content' => { value: 'B...' } }, transitions: [{rel: 'self', href: '/foo2'}]},
|
159
|
+
{attributes: {'content' => { value: 'C...' } }, transitions: [{rel: 'self', href: '/foo3'}]}
|
160
|
+
]
|
161
|
+
}
|
162
|
+
}
|
163
|
+
end
|
164
|
+
|
165
|
+
it_behaves_like 'a hal documents attributes', representor_hash
|
166
|
+
it_behaves_like 'a hal documents links', representor_hash
|
167
|
+
it_behaves_like 'a hal documents embedded collection', representor_hash
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|