rest-in-peace 1.4.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/README.md +75 -2
- data/VERSION +1 -1
- data/lib/rest_in_peace/active_model_api.rb +72 -0
- data/lib/rest_in_peace/definition_proxy/attributes_definitions.rb +20 -0
- data/lib/rest_in_peace/definition_proxy/collection_method_definitions.rb +1 -0
- data/lib/rest_in_peace/definition_proxy/resource_method_definitions.rb +7 -8
- data/lib/rest_in_peace/definition_proxy.rb +21 -0
- data/lib/rest_in_peace/faraday/raise_errors_middleware.rb +34 -0
- data/lib/rest_in_peace/faraday/ssl_config_creator.rb +66 -0
- data/lib/rest_in_peace/response_converter.rb +28 -12
- data/lib/rest_in_peace/template_sanitizer.rb +1 -1
- data/lib/rest_in_peace.rb +45 -9
- data/rest-in-peace.gemspec +5 -3
- data/spec/rest_in_peace/active_model_api_spec.rb +201 -0
- data/spec/rest_in_peace/definition_proxy/attributes_definitions_spec.rb +36 -0
- data/spec/rest_in_peace/definition_proxy/collection_method_definitions_spec.rb +7 -2
- data/spec/rest_in_peace/definition_proxy/resource_method_definitions_spec.rb +69 -13
- data/spec/rest_in_peace/definition_proxy_spec.rb +34 -1
- data/spec/rest_in_peace/response_converter_spec.rb +22 -5
- data/spec/rest_in_peace/template_sanitizer_spec.rb +12 -0
- data/spec/rest_in_peace_spec.rb +140 -7
- data/spec/spec_helper.rb +4 -1
- metadata +51 -18
- data/lib/rest_in_peace/ssl_config_creator.rb +0 -59
@@ -0,0 +1,201 @@
|
|
1
|
+
require 'rest_in_peace'
|
2
|
+
require 'rest_in_peace/active_model_api'
|
3
|
+
require 'ostruct'
|
4
|
+
|
5
|
+
describe RESTinPeace do
|
6
|
+
let(:api_double) { double('IamAnAPI') }
|
7
|
+
let(:response) { OpenStruct.new(body: 'string!') }
|
8
|
+
let(:extended_class) do
|
9
|
+
Class.new do
|
10
|
+
include RESTinPeace
|
11
|
+
|
12
|
+
rest_in_peace do
|
13
|
+
attributes do
|
14
|
+
read :id, :name
|
15
|
+
write :description, :title
|
16
|
+
end
|
17
|
+
|
18
|
+
resource do
|
19
|
+
put :save, '/class/:id'
|
20
|
+
post :create, '/class'
|
21
|
+
end
|
22
|
+
|
23
|
+
acts_as_active_model
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
let(:id) { 1 }
|
29
|
+
let(:name) { 'pony one' }
|
30
|
+
let(:description) { nil }
|
31
|
+
let(:attributes) do
|
32
|
+
{
|
33
|
+
id: id,
|
34
|
+
name: name,
|
35
|
+
description: description,
|
36
|
+
}
|
37
|
+
end
|
38
|
+
let(:instance) { extended_class.new(attributes) }
|
39
|
+
|
40
|
+
context 'class methods' do
|
41
|
+
describe '::acts_as_active_model' do
|
42
|
+
context 'missing save method' do
|
43
|
+
let(:extended_class) do
|
44
|
+
Class.new do
|
45
|
+
include RESTinPeace
|
46
|
+
rest_in_peace do
|
47
|
+
acts_as_active_model
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'raises an error when no save method specified' do
|
53
|
+
expect { extended_class.new }.to raise_error(RESTinPeace::ActiveModelAPI::MissingMethod)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'missing create method' do
|
58
|
+
let(:extended_class) do
|
59
|
+
Class.new do
|
60
|
+
include RESTinPeace
|
61
|
+
rest_in_peace do
|
62
|
+
resource do
|
63
|
+
put :save, '/yolo'
|
64
|
+
end
|
65
|
+
acts_as_active_model
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'raises an error when no create method specified' do
|
71
|
+
expect { extended_class.new }.to raise_error(RESTinPeace::ActiveModelAPI::MissingMethod)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe '::model_name' do
|
77
|
+
before do
|
78
|
+
def extended_class.model_name
|
79
|
+
ActiveModel::Name.new(self, nil, 'TemporaryClassForTests')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
specify { expect(extended_class.model_name).to eq('TemporaryClassForTests') }
|
83
|
+
specify { expect(extended_class.model_name).to respond_to(:route_key) }
|
84
|
+
end
|
85
|
+
|
86
|
+
describe 'validation handling' do
|
87
|
+
specify { expect(extended_class).to respond_to(:human_attribute_name).with(2).arguments }
|
88
|
+
specify { expect(extended_class.human_attribute_name(:description)).to eq('description') }
|
89
|
+
|
90
|
+
specify { expect(extended_class).to respond_to(:lookup_ancestors).with(0).arguments }
|
91
|
+
specify { expect(extended_class.lookup_ancestors).to eq([extended_class]) }
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'instance methods' do
|
96
|
+
before do
|
97
|
+
extended_class.api = api_double
|
98
|
+
allow(api_double).to receive(:put).and_return(response)
|
99
|
+
allow(api_double).to receive(:post).and_return(response)
|
100
|
+
end
|
101
|
+
|
102
|
+
describe '#changed?' do
|
103
|
+
context 'a new instance' do
|
104
|
+
specify { expect(instance.changed?).to eq(false) }
|
105
|
+
end
|
106
|
+
|
107
|
+
context 'a modified instance' do
|
108
|
+
before do
|
109
|
+
instance.description = 'new value'
|
110
|
+
end
|
111
|
+
specify { expect(instance.changed?).to eq(true) }
|
112
|
+
end
|
113
|
+
|
114
|
+
context 'a saved instance' do
|
115
|
+
before do
|
116
|
+
instance.description = 'new value'
|
117
|
+
instance.save
|
118
|
+
end
|
119
|
+
specify { expect(instance.changed?).to eq(false) }
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe 'attribute methods' do
|
124
|
+
specify { expect(instance).to respond_to(:description_changed?) }
|
125
|
+
specify { expect(instance).to respond_to(:title_changed?) }
|
126
|
+
end
|
127
|
+
|
128
|
+
describe '#to_key' do
|
129
|
+
specify { expect(instance.to_key).to eq([1]) }
|
130
|
+
end
|
131
|
+
|
132
|
+
describe '#persisted?' do
|
133
|
+
context 'persisted model' do
|
134
|
+
specify { expect(instance.persisted?).to eq(true) }
|
135
|
+
end
|
136
|
+
|
137
|
+
context 'not yet persisted model' do
|
138
|
+
let(:id) { nil }
|
139
|
+
specify { expect(instance.persisted?).to eq(false) }
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe '#save' do
|
144
|
+
context 'without errors' do
|
145
|
+
let(:response) { OpenStruct.new(body: { name: 'new name from api' }) }
|
146
|
+
|
147
|
+
specify { expect { instance.save }.to_not raise_error }
|
148
|
+
specify { expect(instance.save.object_id).to eq(instance.object_id) }
|
149
|
+
specify { expect { instance.save }.to change(instance, :name) }
|
150
|
+
end
|
151
|
+
|
152
|
+
context 'with errors' do
|
153
|
+
before do
|
154
|
+
instance.description = 'value!'
|
155
|
+
end
|
156
|
+
let(:response) { OpenStruct.new(body: { errors: { 'description' => ['is not empty'] } }) }
|
157
|
+
|
158
|
+
specify { expect { instance.save }.to change { instance.errors.any? } }
|
159
|
+
specify { expect { instance.save }.to_not change { instance.description } }
|
160
|
+
specify { expect { instance.save }.to_not change { instance.name } }
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
describe '#create' do
|
165
|
+
context 'without errors' do
|
166
|
+
let(:response) { OpenStruct.new(body: { name: 'new name from api' }) }
|
167
|
+
|
168
|
+
specify { expect { instance.create }.to_not raise_error }
|
169
|
+
specify { expect(instance.create.object_id).to eq(instance.object_id) }
|
170
|
+
specify { expect { instance.create }.to change(instance, :name) }
|
171
|
+
end
|
172
|
+
|
173
|
+
context 'with errors' do
|
174
|
+
before do
|
175
|
+
instance.description = 'value!'
|
176
|
+
end
|
177
|
+
let(:response) { OpenStruct.new(body: { errors: { 'description' => ['is not empty'] } }) }
|
178
|
+
|
179
|
+
specify { expect { instance.create }.to change { instance.errors.any? } }
|
180
|
+
specify { expect { instance.create }.to_not change { instance.description } }
|
181
|
+
specify { expect { instance.create }.to_not change { instance.name } }
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
describe 'validation handling' do
|
186
|
+
let(:description) { 'desc' }
|
187
|
+
|
188
|
+
specify { expect(instance).to respond_to(:read_attribute_for_validation).with(1).argument }
|
189
|
+
specify { expect(instance.read_attribute_for_validation(:description)).to eq('desc') }
|
190
|
+
|
191
|
+
describe '#errors' do
|
192
|
+
specify { expect(instance.errors).to be_instance_of(ActiveModel::Errors) }
|
193
|
+
end
|
194
|
+
|
195
|
+
describe '#errors=' do
|
196
|
+
let(:errors) { { description: ['must not be empty'] } }
|
197
|
+
specify { expect { instance.errors = errors }.to change { instance.errors.count } }
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'rest_in_peace'
|
2
|
+
require 'rest_in_peace/definition_proxy/attributes_definitions'
|
3
|
+
|
4
|
+
describe RESTinPeace::DefinitionProxy::AttributesDefinitions do
|
5
|
+
let(:target) do
|
6
|
+
Class.new do
|
7
|
+
include RESTinPeace
|
8
|
+
end
|
9
|
+
end
|
10
|
+
let(:instance_of_target) { target.new }
|
11
|
+
let(:definitions) { described_class.new(target) }
|
12
|
+
|
13
|
+
subject { definitions }
|
14
|
+
|
15
|
+
describe '#read' do
|
16
|
+
it 'defines a getter for the given attributes' do
|
17
|
+
expect { subject.read(:id) }.to change { instance_of_target.respond_to?(:id) }.from(false).to(true)
|
18
|
+
end
|
19
|
+
it 'does not define a setter for the given attributes' do
|
20
|
+
expect { subject.read(:id) }.to_not change { instance_of_target.respond_to?(:id=) }.from(false)
|
21
|
+
end
|
22
|
+
specify { expect { subject.read(:id) }.to change { target.rip_attributes[:read] }.from([]).to([:id]) }
|
23
|
+
specify { expect { subject.read(:id) }.to_not change { target.rip_attributes[:write] }.from([]) }
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#write' do
|
27
|
+
it 'defines a getter for the given attributes' do
|
28
|
+
expect { subject.write(:id) }.to change { instance_of_target.respond_to?(:id) }.from(false).to(true)
|
29
|
+
end
|
30
|
+
it 'defines a setter for the given attributes' do
|
31
|
+
expect { subject.write(:id) }.to change { instance_of_target.respond_to?(:id=) }.from(false).to(true)
|
32
|
+
end
|
33
|
+
specify { expect { subject.write(:id) }.to change { target.rip_attributes[:read] }.from([]).to([:id]) }
|
34
|
+
specify { expect { subject.write(:id) }.to change { target.rip_attributes[:write] }.from([]).to([:id]) }
|
35
|
+
end
|
36
|
+
end
|
@@ -5,9 +5,8 @@ describe RESTinPeace::DefinitionProxy::CollectionMethodDefinitions do
|
|
5
5
|
let(:method_name) { :find }
|
6
6
|
let(:url_template) { '/a/:id' }
|
7
7
|
let(:default_params) { {} }
|
8
|
-
let(:struct) { Struct.new(:id, :name) }
|
9
8
|
let(:target) do
|
10
|
-
Class.new
|
9
|
+
Class.new do
|
11
10
|
include RESTinPeace
|
12
11
|
end
|
13
12
|
end
|
@@ -71,6 +70,12 @@ describe RESTinPeace::DefinitionProxy::CollectionMethodDefinitions do
|
|
71
70
|
target.find(id: 1)
|
72
71
|
expect(default_params).to eq({ per_page: 250 })
|
73
72
|
end
|
73
|
+
|
74
|
+
it 'raises an error when param is not a hash' do
|
75
|
+
subject.get(:find, '/a/:id', default_params)
|
76
|
+
|
77
|
+
expect { target.find(1) }.to raise_error(RESTinPeace::DefinitionProxy::InvalidArgument)
|
78
|
+
end
|
74
79
|
end
|
75
80
|
|
76
81
|
context 'without any attributes' do
|
@@ -2,10 +2,16 @@ require 'rest_in_peace'
|
|
2
2
|
require 'rest_in_peace/definition_proxy/resource_method_definitions'
|
3
3
|
|
4
4
|
describe RESTinPeace::DefinitionProxy::ResourceMethodDefinitions do
|
5
|
-
let(:struct) { Struct.new(:id, :name) }
|
6
5
|
let(:target) do
|
7
|
-
Class.new
|
6
|
+
Class.new do
|
8
7
|
include RESTinPeace
|
8
|
+
rest_in_peace do
|
9
|
+
attributes do
|
10
|
+
read :id
|
11
|
+
write :name
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
9
15
|
end
|
10
16
|
end
|
11
17
|
let(:instance) { target.new }
|
@@ -16,6 +22,7 @@ describe RESTinPeace::DefinitionProxy::ResourceMethodDefinitions do
|
|
16
22
|
|
17
23
|
before do
|
18
24
|
allow(RESTinPeace::ApiCall).to receive(:new).and_return(api_call_double)
|
25
|
+
allow(api_call_double).to receive(http_verb)
|
19
26
|
end
|
20
27
|
|
21
28
|
shared_examples_for 'an instance method' do
|
@@ -28,21 +35,30 @@ describe RESTinPeace::DefinitionProxy::ResourceMethodDefinitions do
|
|
28
35
|
subject.send(http_verb, method_name, url_template)
|
29
36
|
expect(target.rip_registry[:resource]).to eq([method: http_verb, name: method_name, url: url_template])
|
30
37
|
end
|
38
|
+
end
|
31
39
|
|
32
|
-
|
33
|
-
|
34
|
-
|
40
|
+
shared_examples_for 'an instance method with parameters' do
|
41
|
+
describe 'parameter and arguments handling' do
|
42
|
+
it 'uses the attributes of the class' do
|
43
|
+
expect(RESTinPeace::ApiCall).to receive(:new).
|
44
|
+
with(target.api, url_template, instance, instance.hash_for_updates).
|
45
|
+
and_return(api_call_double)
|
46
|
+
|
47
|
+
subject.send(http_verb, method_name, url_template)
|
48
|
+
instance.send(method_name)
|
35
49
|
end
|
50
|
+
end
|
51
|
+
end
|
36
52
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
53
|
+
shared_examples_for 'an instance method without parameters' do
|
54
|
+
describe 'parameter and arguments handling' do
|
55
|
+
it 'provides the id only' do
|
56
|
+
expect(RESTinPeace::ApiCall).to receive(:new).
|
57
|
+
with(target.api, url_template, instance, id: instance.id).
|
58
|
+
and_return(api_call_double)
|
42
59
|
|
43
|
-
|
44
|
-
|
45
|
-
end
|
60
|
+
subject.send(http_verb, method_name, url_template)
|
61
|
+
instance.send(method_name)
|
46
62
|
end
|
47
63
|
end
|
48
64
|
end
|
@@ -53,6 +69,14 @@ describe RESTinPeace::DefinitionProxy::ResourceMethodDefinitions do
|
|
53
69
|
let(:method_name) { :reload }
|
54
70
|
let(:url_template) { '/a/:id' }
|
55
71
|
end
|
72
|
+
|
73
|
+
describe 'the created method' do
|
74
|
+
it_behaves_like 'an instance method with parameters' do
|
75
|
+
let(:http_verb) { :get }
|
76
|
+
let(:method_name) { :reload }
|
77
|
+
let(:url_template) { '/a/:id' }
|
78
|
+
end
|
79
|
+
end
|
56
80
|
end
|
57
81
|
|
58
82
|
context '#patch' do
|
@@ -61,6 +85,14 @@ describe RESTinPeace::DefinitionProxy::ResourceMethodDefinitions do
|
|
61
85
|
let(:method_name) { :save }
|
62
86
|
let(:url_template) { '/a/:id' }
|
63
87
|
end
|
88
|
+
|
89
|
+
describe 'the created method' do
|
90
|
+
it_behaves_like 'an instance method with parameters' do
|
91
|
+
let(:http_verb) { :patch }
|
92
|
+
let(:method_name) { :save }
|
93
|
+
let(:url_template) { '/a/:id' }
|
94
|
+
end
|
95
|
+
end
|
64
96
|
end
|
65
97
|
|
66
98
|
context '#post' do
|
@@ -69,6 +101,14 @@ describe RESTinPeace::DefinitionProxy::ResourceMethodDefinitions do
|
|
69
101
|
let(:method_name) { :create }
|
70
102
|
let(:url_template) { '/a/:id' }
|
71
103
|
end
|
104
|
+
|
105
|
+
describe 'the created method' do
|
106
|
+
it_behaves_like 'an instance method with parameters' do
|
107
|
+
let(:http_verb) { :post }
|
108
|
+
let(:method_name) { :create }
|
109
|
+
let(:url_template) { '/a/:id' }
|
110
|
+
end
|
111
|
+
end
|
72
112
|
end
|
73
113
|
|
74
114
|
context '#put' do
|
@@ -77,6 +117,14 @@ describe RESTinPeace::DefinitionProxy::ResourceMethodDefinitions do
|
|
77
117
|
let(:method_name) { :update }
|
78
118
|
let(:url_template) { '/a/:id' }
|
79
119
|
end
|
120
|
+
|
121
|
+
describe 'the created method' do
|
122
|
+
it_behaves_like 'an instance method with parameters' do
|
123
|
+
let(:http_verb) { :put }
|
124
|
+
let(:method_name) { :update }
|
125
|
+
let(:url_template) { '/a/:id' }
|
126
|
+
end
|
127
|
+
end
|
80
128
|
end
|
81
129
|
|
82
130
|
context '#delete' do
|
@@ -85,6 +133,14 @@ describe RESTinPeace::DefinitionProxy::ResourceMethodDefinitions do
|
|
85
133
|
let(:method_name) { :destroy }
|
86
134
|
let(:url_template) { '/a/:id' }
|
87
135
|
end
|
136
|
+
|
137
|
+
describe 'the created method' do
|
138
|
+
it_behaves_like 'an instance method without parameters' do
|
139
|
+
let(:http_verb) { :delete }
|
140
|
+
let(:method_name) { :destroy }
|
141
|
+
let(:url_template) { '/a/:id' }
|
142
|
+
end
|
143
|
+
end
|
88
144
|
end
|
89
145
|
|
90
146
|
end
|
@@ -1,9 +1,12 @@
|
|
1
|
+
require 'rest_in_peace'
|
1
2
|
require 'rest_in_peace/definition_proxy'
|
3
|
+
require 'ostruct'
|
2
4
|
|
3
5
|
describe RESTinPeace::DefinitionProxy do
|
4
6
|
let(:resource_definitions) { object_double(RESTinPeace::DefinitionProxy::ResourceMethodDefinitions) }
|
5
7
|
let(:collection_definitions) { object_double(RESTinPeace::DefinitionProxy::CollectionMethodDefinitions) }
|
6
|
-
let(:
|
8
|
+
let(:attributes_definitions) { object_double(RESTinPeace::DefinitionProxy::AttributesDefinitions) }
|
9
|
+
let(:target) { double('Target') }
|
7
10
|
let(:proxy) { RESTinPeace::DefinitionProxy.new(target) }
|
8
11
|
let(:test_proc) { ->() {} }
|
9
12
|
|
@@ -14,6 +17,8 @@ describe RESTinPeace::DefinitionProxy do
|
|
14
17
|
to receive(:new).with(target).and_return(resource_definitions)
|
15
18
|
allow(RESTinPeace::DefinitionProxy::CollectionMethodDefinitions).
|
16
19
|
to receive(:new).with(target).and_return(collection_definitions)
|
20
|
+
allow(RESTinPeace::DefinitionProxy::AttributesDefinitions).
|
21
|
+
to receive(:new).with(target).and_return(attributes_definitions)
|
17
22
|
end
|
18
23
|
|
19
24
|
describe '#resource' do
|
@@ -33,4 +38,32 @@ describe RESTinPeace::DefinitionProxy do
|
|
33
38
|
subject.collection(&test_proc)
|
34
39
|
end
|
35
40
|
end
|
41
|
+
|
42
|
+
describe '#attributes' do
|
43
|
+
it 'forwards the given block to a attributes method definition' do
|
44
|
+
expect(attributes_definitions).to receive(:instance_eval) do |&block|
|
45
|
+
expect(block).to be_instance_of(Proc)
|
46
|
+
end
|
47
|
+
subject.attributes(&test_proc)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '#namespace_attributes_with' do
|
52
|
+
let(:target) do
|
53
|
+
Class.new do
|
54
|
+
include RESTinPeace
|
55
|
+
end
|
56
|
+
end
|
57
|
+
it 'configures the namespace' do
|
58
|
+
expect { subject.namespace_attributes_with(:blubb) }.
|
59
|
+
to change { target.rip_namespace }.from(nil).to(:blubb)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '#acts_as_active_model' do
|
64
|
+
it 'includes RESTinPeace::ActiveModelAPI' do
|
65
|
+
expect(target).to receive(:include).with(RESTinPeace::ActiveModelAPI)
|
66
|
+
subject.acts_as_active_model
|
67
|
+
end
|
68
|
+
end
|
36
69
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'rest_in_peace'
|
1
2
|
require 'rest_in_peace/response_converter'
|
2
3
|
require 'ostruct'
|
3
4
|
|
@@ -6,6 +7,16 @@ describe RESTinPeace::ResponseConverter do
|
|
6
7
|
let(:element2) { { name: 'test2' } }
|
7
8
|
let(:response) { OpenStruct.new(body: response_body) }
|
8
9
|
let(:converter) { RESTinPeace::ResponseConverter.new(response, klass) }
|
10
|
+
let(:extended_class) do
|
11
|
+
Class.new do
|
12
|
+
include RESTinPeace
|
13
|
+
rest_in_peace do
|
14
|
+
attributes do
|
15
|
+
read :name
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
9
20
|
|
10
21
|
describe '#result' do
|
11
22
|
subject { converter.result }
|
@@ -13,13 +24,14 @@ describe RESTinPeace::ResponseConverter do
|
|
13
24
|
shared_examples_for 'an array input' do
|
14
25
|
let(:response_body) { [element1, element2] }
|
15
26
|
specify { expect(subject).to be_instance_of(Array) }
|
16
|
-
specify { expect(subject).to
|
27
|
+
specify { expect(subject.first).to be_instance_of(extended_class) }
|
28
|
+
specify { expect(subject.map(&:name)).to eq(%w(test1 test2)) }
|
17
29
|
end
|
18
30
|
|
19
31
|
shared_examples_for 'a hash input' do
|
20
32
|
let(:response_body) { element1 }
|
21
|
-
specify { expect(subject).to be_instance_of(
|
22
|
-
specify { expect(subject).to eq(
|
33
|
+
specify { expect(subject).to be_instance_of(extended_class) }
|
34
|
+
specify { expect(subject.name).to eq('test1') }
|
23
35
|
end
|
24
36
|
|
25
37
|
shared_examples_for 'a string input' do
|
@@ -28,8 +40,13 @@ describe RESTinPeace::ResponseConverter do
|
|
28
40
|
specify { expect(subject).to eq('yolo binary stuff') }
|
29
41
|
end
|
30
42
|
|
43
|
+
shared_examples_for 'an unknown input do' do
|
44
|
+
let(:response_body) { Object }
|
45
|
+
specify { expect { subject }.to raise_error(RESTinPeace::ResponseConverter::UnknownConvertStrategy) }
|
46
|
+
end
|
47
|
+
|
31
48
|
context 'given type is a class' do
|
32
|
-
let(:klass) {
|
49
|
+
let(:klass) { extended_class }
|
33
50
|
context 'input is an array' do
|
34
51
|
it_behaves_like 'an array input'
|
35
52
|
end
|
@@ -44,7 +61,7 @@ describe RESTinPeace::ResponseConverter do
|
|
44
61
|
end
|
45
62
|
|
46
63
|
context 'given type is an instance' do
|
47
|
-
let(:klass) {
|
64
|
+
let(:klass) { extended_class.new }
|
48
65
|
context 'input is an array' do
|
49
66
|
it_behaves_like 'an array input'
|
50
67
|
end
|
@@ -19,6 +19,18 @@ describe RESTinPeace::TemplateSanitizer do
|
|
19
19
|
specify { expect(subject).to eq('/a/1/b/2') }
|
20
20
|
end
|
21
21
|
|
22
|
+
context 'tokens with substrings' do
|
23
|
+
let(:params) { { element: 'asd', element_id: 1 } }
|
24
|
+
let(:url_template) { '/a/:element/b/:element_id' }
|
25
|
+
specify { expect(subject).to eq('/a/asd/b/1') }
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'tokens with substrings, reverse order' do
|
29
|
+
let(:params) { { element: 'asd', element_id: 1 } }
|
30
|
+
let(:url_template) { '/a/:element_id/b/:element' }
|
31
|
+
specify { expect(subject).to eq('/a/1/b/asd') }
|
32
|
+
end
|
33
|
+
|
22
34
|
context 'incomplete params' do
|
23
35
|
let(:params) { {} }
|
24
36
|
let(:url_template) { '/a/:id' }
|