puppet_forge 1.0.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.
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +13 -0
- data/README.md +172 -0
- data/Rakefile +2 -0
- data/lib/her/lazy_accessors.rb +140 -0
- data/lib/her/lazy_relations.rb +86 -0
- data/lib/puppet_forge.rb +19 -0
- data/lib/puppet_forge/middleware/json_for_her.rb +37 -0
- data/lib/puppet_forge/v3.rb +10 -0
- data/lib/puppet_forge/v3/base.rb +98 -0
- data/lib/puppet_forge/v3/base/paginated_collection.rb +73 -0
- data/lib/puppet_forge/v3/module.rb +15 -0
- data/lib/puppet_forge/v3/release.rb +35 -0
- data/lib/puppet_forge/v3/user.rb +21 -0
- data/lib/puppet_forge/version.rb +3 -0
- data/puppet_forge.gemspec +31 -0
- data/spec/fixtures/v3/files/puppetlabs-apache-0.0.1.tar.gz.headers +14 -0
- data/spec/fixtures/v3/files/puppetlabs-apache-0.0.1.tar.gz.json +0 -0
- data/spec/fixtures/v3/modules.headers +14 -0
- data/spec/fixtures/v3/modules.json +4197 -0
- data/spec/fixtures/v3/modules/puppetlabs-apache.headers +14 -0
- data/spec/fixtures/v3/modules/puppetlabs-apache.json +390 -0
- data/spec/fixtures/v3/modules?owner=puppetlabs.headers +14 -0
- data/spec/fixtures/v3/modules?owner=puppetlabs.json +4179 -0
- data/spec/fixtures/v3/modules?query=apache.headers +14 -0
- data/spec/fixtures/v3/modules?query=apache.json +3151 -0
- data/spec/fixtures/v3/releases.headers +14 -0
- data/spec/fixtures/v3/releases.json +3072 -0
- data/spec/fixtures/v3/releases/puppetlabs-apache-0.0.1.headers +14 -0
- data/spec/fixtures/v3/releases/puppetlabs-apache-0.0.1.json +93 -0
- data/spec/fixtures/v3/releases/puppetlabs-apache-0.0.2.headers +14 -0
- data/spec/fixtures/v3/releases/puppetlabs-apache-0.0.2.json +93 -0
- data/spec/fixtures/v3/releases/puppetlabs-apache-0.0.3.headers +14 -0
- data/spec/fixtures/v3/releases/puppetlabs-apache-0.0.3.json +93 -0
- data/spec/fixtures/v3/releases/puppetlabs-apache-0.0.4.headers +14 -0
- data/spec/fixtures/v3/releases/puppetlabs-apache-0.0.4.json +126 -0
- data/spec/fixtures/v3/releases/puppetlabs-apache-0.1.1.headers +14 -0
- data/spec/fixtures/v3/releases/puppetlabs-apache-0.1.1.json +140 -0
- data/spec/fixtures/v3/releases?module=puppetlabs-apache.headers +14 -0
- data/spec/fixtures/v3/releases?module=puppetlabs-apache.json +3287 -0
- data/spec/fixtures/v3/users/puppetlabs.headers +14 -0
- data/spec/fixtures/v3/users/puppetlabs.json +10 -0
- data/spec/spec_helper.rb +60 -0
- data/spec/unit/forge/v3/base/paginated_collection_spec.rb +88 -0
- data/spec/unit/forge/v3/module_spec.rb +118 -0
- data/spec/unit/forge/v3/release_spec.rb +112 -0
- data/spec/unit/forge/v3/user_spec.rb +50 -0
- data/spec/unit/her/lazy_accessors_spec.rb +142 -0
- data/spec/unit/her/lazy_relations_spec.rb +309 -0
- metadata +261 -0
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
describe Her::LazyAccessors do
|
5
|
+
let(:klass) do
|
6
|
+
Class.new do
|
7
|
+
include Her::Model
|
8
|
+
include Her::LazyAccessors
|
9
|
+
|
10
|
+
def request_path
|
11
|
+
"/things/#{id}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def standalone_method
|
15
|
+
"a/b/c"
|
16
|
+
end
|
17
|
+
|
18
|
+
def satisified_dependent_method
|
19
|
+
"-#{local}-"
|
20
|
+
end
|
21
|
+
|
22
|
+
def unsatisfied_dependent_method
|
23
|
+
"-#{remote}-"
|
24
|
+
end
|
25
|
+
|
26
|
+
def shadow
|
27
|
+
"-#{super}-"
|
28
|
+
end
|
29
|
+
|
30
|
+
def remote_shadow
|
31
|
+
"-#{super}-"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
let(:local_data) { { :id => 1, :local => 'data', :shadow => 'x' } }
|
37
|
+
let(:remote_data) { local_data.merge(:remote => 'DATA', :remote_shadow => 'X') }
|
38
|
+
|
39
|
+
subject { klass.new(local_data) }
|
40
|
+
|
41
|
+
it 'does not call methods to #inspect' do
|
42
|
+
subject.should_not_receive(:shadow)
|
43
|
+
subject.inspect
|
44
|
+
end
|
45
|
+
|
46
|
+
describe 'local attributes' do
|
47
|
+
before { klass.should_not_receive(:request) }
|
48
|
+
|
49
|
+
example 'allow access to local attributes' do
|
50
|
+
expect(subject.local).to eql('data')
|
51
|
+
end
|
52
|
+
|
53
|
+
example 'provide local attributes predicates' do
|
54
|
+
expect(subject.local?).to be true
|
55
|
+
end
|
56
|
+
|
57
|
+
example 'provide local attributes setters' do
|
58
|
+
subject.local = 'foo'
|
59
|
+
expect(subject.local).to eql('foo')
|
60
|
+
end
|
61
|
+
|
62
|
+
example 'allow access to local standalone methods' do
|
63
|
+
expect(subject.standalone_method).to eql('a/b/c')
|
64
|
+
end
|
65
|
+
|
66
|
+
example 'allow access to locally satisfiable methods' do
|
67
|
+
expect(subject.satisified_dependent_method).to eql('-data-')
|
68
|
+
end
|
69
|
+
|
70
|
+
example 'allow `super` access to shadowed attributes' do
|
71
|
+
expect(subject.shadow).to eql('-x-')
|
72
|
+
end
|
73
|
+
|
74
|
+
example 'do not create accessors on the base class itself' do
|
75
|
+
expect(klass.instance_methods(false)).to_not include(:local)
|
76
|
+
subject.local rescue nil
|
77
|
+
expect(klass.instance_methods(false)).to_not include(:local)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe 'remote attributes' do
|
82
|
+
before do
|
83
|
+
stub_api_for(klass) do |api|
|
84
|
+
api.get('/things/1') do
|
85
|
+
[ 200, { 'Content-Type' => 'json' }, remote_data.to_json ]
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
example 'allow access to remote attributes' do
|
91
|
+
expect(subject.remote).to eql('DATA')
|
92
|
+
end
|
93
|
+
|
94
|
+
example 'provide remote attributes predicates' do
|
95
|
+
expect(subject.remote?).to be true
|
96
|
+
end
|
97
|
+
|
98
|
+
example 'provide remote attributes setters' do
|
99
|
+
subject.remote = 'foo'
|
100
|
+
expect(subject.remote).to eql('foo')
|
101
|
+
end
|
102
|
+
|
103
|
+
example 'allow multiple instances to access remote attributes' do
|
104
|
+
klass.should_receive(:request).exactly(9).times.and_call_original
|
105
|
+
9.times { expect(klass.new(local_data).remote).to eql('DATA') }
|
106
|
+
end
|
107
|
+
|
108
|
+
example 'allow access to locally unsatisfiable methods' do
|
109
|
+
expect(subject.unsatisfied_dependent_method).to eql('-DATA-')
|
110
|
+
end
|
111
|
+
|
112
|
+
example 'allow `super` access to shadowed remote attributes' do
|
113
|
+
expect(subject.remote_shadow).to eql('-X-')
|
114
|
+
end
|
115
|
+
|
116
|
+
example 'do not create accessors on the base class itself' do
|
117
|
+
expect(klass.instance_methods(false)).to_not include(:remote)
|
118
|
+
subject.remote rescue nil
|
119
|
+
expect(klass.instance_methods(false)).to_not include(:remote)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe 'unsatisfiable attributes' do
|
124
|
+
before do
|
125
|
+
stub_api_for(klass) do |api|
|
126
|
+
api.get('/things/1') do
|
127
|
+
[ 200, { 'Content-Type' => 'json' }, remote_data.to_json ]
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
example 'raise an exception when accessing an unknown attribute' do
|
133
|
+
expect { subject.unknown_attribute }.to raise_error(NoMethodError)
|
134
|
+
end
|
135
|
+
|
136
|
+
example 'do not create accessors on the base class itself' do
|
137
|
+
expect(klass.instance_methods(false)).to_not include(:local)
|
138
|
+
subject.unknown_attribute rescue nil
|
139
|
+
expect(klass.instance_methods(false)).to_not include(:local)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,309 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
describe Her::LazyRelations do
|
5
|
+
let(:klass) do |*args|
|
6
|
+
ctx = self
|
7
|
+
|
8
|
+
Class.new do
|
9
|
+
include Her::Model
|
10
|
+
include Her::LazyRelations
|
11
|
+
|
12
|
+
lazy :relation, ctx.related_class
|
13
|
+
lazy :chained, self
|
14
|
+
lazy_collection :relations, ctx.related_class
|
15
|
+
lazy_collection :parents, self
|
16
|
+
|
17
|
+
def request_path
|
18
|
+
"/parents/#{id}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:related_class) do
|
24
|
+
Class.new do
|
25
|
+
include Her::Model
|
26
|
+
|
27
|
+
def request_path
|
28
|
+
"/things/#{id}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def standalone_method
|
32
|
+
"a/b/c"
|
33
|
+
end
|
34
|
+
|
35
|
+
def satisified_dependent_method
|
36
|
+
"-#{local}-"
|
37
|
+
end
|
38
|
+
|
39
|
+
def unsatisfied_dependent_method
|
40
|
+
"-#{remote}-"
|
41
|
+
end
|
42
|
+
|
43
|
+
def shadow
|
44
|
+
"-#{super}-"
|
45
|
+
end
|
46
|
+
|
47
|
+
def remote_shadow
|
48
|
+
"-#{super}-"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
let(:local_data) { { :id => 1, :local => 'data', :shadow => 'x' } }
|
54
|
+
let(:remote_data) { local_data.merge(:remote => 'DATA', :remote_shadow => 'X') }
|
55
|
+
|
56
|
+
describe '.lazy' do
|
57
|
+
subject { klass.new(:relation => local_data).relation }
|
58
|
+
|
59
|
+
it { should be_a(related_class) }
|
60
|
+
|
61
|
+
it 'does not call methods to #inspect' do
|
62
|
+
subject.should_not_receive(:shadow)
|
63
|
+
subject.inspect
|
64
|
+
end
|
65
|
+
|
66
|
+
describe 'local attributes' do
|
67
|
+
before { related_class.should_not_receive(:request) }
|
68
|
+
|
69
|
+
example 'allow access to local attributes' do
|
70
|
+
expect(subject.local).to eql('data')
|
71
|
+
end
|
72
|
+
|
73
|
+
example 'provide local attributes predicates' do
|
74
|
+
expect(subject.local?).to be true
|
75
|
+
end
|
76
|
+
|
77
|
+
example 'provide local attributes setters' do
|
78
|
+
subject.local = 'foo'
|
79
|
+
expect(subject.local).to eql('foo')
|
80
|
+
end
|
81
|
+
|
82
|
+
example 'allow access to local standalone methods' do
|
83
|
+
expect(subject.standalone_method).to eql('a/b/c')
|
84
|
+
end
|
85
|
+
|
86
|
+
example 'allow access to locally satisfiable methods' do
|
87
|
+
expect(subject.satisified_dependent_method).to eql('-data-')
|
88
|
+
end
|
89
|
+
|
90
|
+
example 'allow `super` access to shadowed attributes' do
|
91
|
+
expect(subject.shadow).to eql('-x-')
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe 'remote attributes' do
|
96
|
+
before do
|
97
|
+
stub_api_for(related_class) do |api|
|
98
|
+
api.get('/things/1') do
|
99
|
+
[ 200, { 'Content-Type' => 'json' }, remote_data.to_json ]
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
example 'allow access to remote attributes' do
|
105
|
+
expect(subject.remote).to eql('DATA')
|
106
|
+
end
|
107
|
+
|
108
|
+
example 'provide remote attributes predicates' do
|
109
|
+
expect(subject.remote?).to be true
|
110
|
+
end
|
111
|
+
|
112
|
+
example 'provide remote attributes setters' do
|
113
|
+
subject.remote = 'foo'
|
114
|
+
expect(subject.remote).to eql('foo')
|
115
|
+
end
|
116
|
+
|
117
|
+
example 'allow multiple instances to access remote attributes' do
|
118
|
+
related_class.should_receive(:request) \
|
119
|
+
.exactly(9).times \
|
120
|
+
.and_call_original
|
121
|
+
|
122
|
+
9.times do
|
123
|
+
subject = klass.new(:relation => local_data).relation
|
124
|
+
expect(subject.remote).to eql('DATA')
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
example 'allow access to locally unsatisfiable methods' do
|
129
|
+
expect(subject.unsatisfied_dependent_method).to eql('-DATA-')
|
130
|
+
end
|
131
|
+
|
132
|
+
example 'allow `super` access to shadowed remote attributes' do
|
133
|
+
expect(subject.remote_shadow).to eql('-X-')
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe 'remote relations' do
|
138
|
+
before do
|
139
|
+
stub_api_for(klass) do |api|
|
140
|
+
api.get('/parents/1') do
|
141
|
+
data = { :id => 1, :relation => local_data }
|
142
|
+
[ 200, { 'Content-Type' => 'json' }, data.to_json ]
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
stub_api_for(related_class) do |api|
|
147
|
+
api.get('/things/1') do
|
148
|
+
[ 200, { 'Content-Type' => 'json' }, remote_data.to_json ]
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
subject { klass.new(:chained => { :id => 1 }) }
|
154
|
+
|
155
|
+
example 'allow chained lookups of lazy relations' do
|
156
|
+
expect(subject.chained.relation.remote).to eql('DATA')
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
describe 'null relations' do
|
161
|
+
subject { klass.new(:relation => nil) }
|
162
|
+
|
163
|
+
example 'do not return new instances' do
|
164
|
+
expect(subject.relation).to be nil
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
describe 'unsatisfiable attributes' do
|
169
|
+
before do
|
170
|
+
stub_api_for(klass) do |api|
|
171
|
+
api.get('/things/1') do
|
172
|
+
[ 200, { 'Content-Type' => 'json' }, remote_data.to_json ]
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
example 'raise an exception when accessing an unknown attribute' do
|
178
|
+
expect { subject.unknown_attribute }.to raise_error(NoMethodError)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
describe '.lazy_collection' do
|
184
|
+
subject { klass.new(:relations => [local_data]).relations.first }
|
185
|
+
|
186
|
+
it { should be_a(related_class) }
|
187
|
+
|
188
|
+
it 'does not call methods to #inspect' do
|
189
|
+
subject.should_not_receive(:shadow)
|
190
|
+
subject.inspect
|
191
|
+
end
|
192
|
+
|
193
|
+
describe 'local attributes' do
|
194
|
+
before { related_class.should_not_receive(:request) }
|
195
|
+
|
196
|
+
example 'allow access to local attributes' do
|
197
|
+
expect(subject.local).to eql('data')
|
198
|
+
end
|
199
|
+
|
200
|
+
example 'provide local attributes predicates' do
|
201
|
+
expect(subject.local?).to be true
|
202
|
+
end
|
203
|
+
|
204
|
+
example 'provide local attributes setters' do
|
205
|
+
subject.local = 'foo'
|
206
|
+
expect(subject.local).to eql('foo')
|
207
|
+
end
|
208
|
+
|
209
|
+
example 'allow access to local standalone methods' do
|
210
|
+
expect(subject.standalone_method).to eql('a/b/c')
|
211
|
+
end
|
212
|
+
|
213
|
+
example 'allow access to locally satisfiable methods' do
|
214
|
+
expect(subject.satisified_dependent_method).to eql('-data-')
|
215
|
+
end
|
216
|
+
|
217
|
+
example 'allow `super` access to shadowed attributes' do
|
218
|
+
expect(subject.shadow).to eql('-x-')
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
describe 'remote attributes' do
|
223
|
+
before do
|
224
|
+
stub_api_for(related_class) do |api|
|
225
|
+
api.get('/things/1') do
|
226
|
+
[ 200, { 'Content-Type' => 'json' }, remote_data.to_json ]
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
example 'allow access to remote attributes' do
|
232
|
+
expect(subject.remote).to eql('DATA')
|
233
|
+
end
|
234
|
+
|
235
|
+
example 'provide remote attributes predicates' do
|
236
|
+
expect(subject.remote?).to be true
|
237
|
+
end
|
238
|
+
|
239
|
+
example 'provide remote attributes setters' do
|
240
|
+
subject.remote = 'foo'
|
241
|
+
expect(subject.remote).to eql('foo')
|
242
|
+
end
|
243
|
+
|
244
|
+
example 'allow multiple instances to access remote attributes' do
|
245
|
+
related_class.should_receive(:request) \
|
246
|
+
.exactly(9).times \
|
247
|
+
.and_call_original
|
248
|
+
|
249
|
+
9.times do
|
250
|
+
subject = klass.new(:relations => [local_data]).relations.first
|
251
|
+
expect(subject.remote).to eql('DATA')
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
example 'allow access to locally unsatisfiable methods' do
|
256
|
+
expect(subject.unsatisfied_dependent_method).to eql('-DATA-')
|
257
|
+
end
|
258
|
+
|
259
|
+
example 'allow `super` access to shadowed remote attributes' do
|
260
|
+
expect(subject.remote_shadow).to eql('-X-')
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
describe 'remote relations' do
|
265
|
+
before do
|
266
|
+
stub_api_for(klass) do |api|
|
267
|
+
api.get('/parents/1') do
|
268
|
+
data = { :id => 1, :parents => [{ :id => 1, :relation => local_data }] }
|
269
|
+
[ 200, { 'Content-Type' => 'json' }, data.to_json ]
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
stub_api_for(related_class) do |api|
|
274
|
+
api.get('/things/1') do
|
275
|
+
[ 200, { 'Content-Type' => 'json' }, remote_data.to_json ]
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
subject { klass.new(:id => 1) }
|
281
|
+
|
282
|
+
example 'allow chained lookups of lazy relations' do
|
283
|
+
expect(subject.parents[0].relation.remote).to eql('DATA')
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
describe 'null relations' do
|
288
|
+
subject { klass.new(:relations => nil) }
|
289
|
+
|
290
|
+
example 'return an empty list' do
|
291
|
+
expect(subject.relations).to be_empty
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
describe 'unsatisfiable attributes' do
|
296
|
+
before do
|
297
|
+
stub_api_for(klass) do |api|
|
298
|
+
api.get('/things/1') do
|
299
|
+
[ 200, { 'Content-Type' => 'json' }, remote_data.to_json ]
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
example 'raise an exception when accessing an unknown attribute' do
|
305
|
+
expect { subject.unknown_attribute }.to raise_error(NoMethodError)
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|