puppet_forge 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/.gitignore +22 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE.txt +13 -0
  4. data/README.md +172 -0
  5. data/Rakefile +2 -0
  6. data/lib/her/lazy_accessors.rb +140 -0
  7. data/lib/her/lazy_relations.rb +86 -0
  8. data/lib/puppet_forge.rb +19 -0
  9. data/lib/puppet_forge/middleware/json_for_her.rb +37 -0
  10. data/lib/puppet_forge/v3.rb +10 -0
  11. data/lib/puppet_forge/v3/base.rb +98 -0
  12. data/lib/puppet_forge/v3/base/paginated_collection.rb +73 -0
  13. data/lib/puppet_forge/v3/module.rb +15 -0
  14. data/lib/puppet_forge/v3/release.rb +35 -0
  15. data/lib/puppet_forge/v3/user.rb +21 -0
  16. data/lib/puppet_forge/version.rb +3 -0
  17. data/puppet_forge.gemspec +31 -0
  18. data/spec/fixtures/v3/files/puppetlabs-apache-0.0.1.tar.gz.headers +14 -0
  19. data/spec/fixtures/v3/files/puppetlabs-apache-0.0.1.tar.gz.json +0 -0
  20. data/spec/fixtures/v3/modules.headers +14 -0
  21. data/spec/fixtures/v3/modules.json +4197 -0
  22. data/spec/fixtures/v3/modules/puppetlabs-apache.headers +14 -0
  23. data/spec/fixtures/v3/modules/puppetlabs-apache.json +390 -0
  24. data/spec/fixtures/v3/modules?owner=puppetlabs.headers +14 -0
  25. data/spec/fixtures/v3/modules?owner=puppetlabs.json +4179 -0
  26. data/spec/fixtures/v3/modules?query=apache.headers +14 -0
  27. data/spec/fixtures/v3/modules?query=apache.json +3151 -0
  28. data/spec/fixtures/v3/releases.headers +14 -0
  29. data/spec/fixtures/v3/releases.json +3072 -0
  30. data/spec/fixtures/v3/releases/puppetlabs-apache-0.0.1.headers +14 -0
  31. data/spec/fixtures/v3/releases/puppetlabs-apache-0.0.1.json +93 -0
  32. data/spec/fixtures/v3/releases/puppetlabs-apache-0.0.2.headers +14 -0
  33. data/spec/fixtures/v3/releases/puppetlabs-apache-0.0.2.json +93 -0
  34. data/spec/fixtures/v3/releases/puppetlabs-apache-0.0.3.headers +14 -0
  35. data/spec/fixtures/v3/releases/puppetlabs-apache-0.0.3.json +93 -0
  36. data/spec/fixtures/v3/releases/puppetlabs-apache-0.0.4.headers +14 -0
  37. data/spec/fixtures/v3/releases/puppetlabs-apache-0.0.4.json +126 -0
  38. data/spec/fixtures/v3/releases/puppetlabs-apache-0.1.1.headers +14 -0
  39. data/spec/fixtures/v3/releases/puppetlabs-apache-0.1.1.json +140 -0
  40. data/spec/fixtures/v3/releases?module=puppetlabs-apache.headers +14 -0
  41. data/spec/fixtures/v3/releases?module=puppetlabs-apache.json +3287 -0
  42. data/spec/fixtures/v3/users/puppetlabs.headers +14 -0
  43. data/spec/fixtures/v3/users/puppetlabs.json +10 -0
  44. data/spec/spec_helper.rb +60 -0
  45. data/spec/unit/forge/v3/base/paginated_collection_spec.rb +88 -0
  46. data/spec/unit/forge/v3/module_spec.rb +118 -0
  47. data/spec/unit/forge/v3/release_spec.rb +112 -0
  48. data/spec/unit/forge/v3/user_spec.rb +50 -0
  49. data/spec/unit/her/lazy_accessors_spec.rb +142 -0
  50. data/spec/unit/her/lazy_relations_spec.rb +309 -0
  51. 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