puppet_forge 1.0.6 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/CHANGELOG.md +23 -0
  2. data/MAINTAINERS +13 -0
  3. data/README.md +48 -6
  4. data/lib/puppet_forge.rb +4 -0
  5. data/lib/puppet_forge/connection.rb +81 -0
  6. data/lib/puppet_forge/connection/connection_failure.rb +26 -0
  7. data/lib/puppet_forge/error.rb +34 -0
  8. data/lib/{her → puppet_forge}/lazy_accessors.rb +20 -27
  9. data/lib/{her → puppet_forge}/lazy_relations.rb +28 -9
  10. data/lib/puppet_forge/middleware/symbolify_json.rb +72 -0
  11. data/lib/puppet_forge/tar.rb +10 -0
  12. data/lib/puppet_forge/tar/mini.rb +81 -0
  13. data/lib/puppet_forge/unpacker.rb +68 -0
  14. data/lib/puppet_forge/v3.rb +11 -0
  15. data/lib/puppet_forge/v3/base.rb +106 -73
  16. data/lib/puppet_forge/v3/base/paginated_collection.rb +23 -14
  17. data/lib/puppet_forge/v3/metadata.rb +197 -0
  18. data/lib/puppet_forge/v3/module.rb +2 -1
  19. data/lib/puppet_forge/v3/release.rb +33 -8
  20. data/lib/puppet_forge/v3/user.rb +2 -0
  21. data/lib/puppet_forge/version.rb +1 -1
  22. data/puppet_forge.gemspec +6 -3
  23. data/spec/fixtures/v3/modules/puppetlabs-apache.json +21 -1
  24. data/spec/fixtures/v3/releases/puppetlabs-apache-0.0.1.json +4 -1
  25. data/spec/integration/forge/v3/module_spec.rb +79 -0
  26. data/spec/integration/forge/v3/release_spec.rb +75 -0
  27. data/spec/integration/forge/v3/user_spec.rb +70 -0
  28. data/spec/spec_helper.rb +15 -8
  29. data/spec/unit/forge/connection/connection_failure_spec.rb +30 -0
  30. data/spec/unit/forge/connection_spec.rb +53 -0
  31. data/spec/unit/{her → forge}/lazy_accessors_spec.rb +20 -13
  32. data/spec/unit/{her → forge}/lazy_relations_spec.rb +60 -46
  33. data/spec/unit/forge/middleware/symbolify_json_spec.rb +63 -0
  34. data/spec/unit/forge/tar/mini_spec.rb +85 -0
  35. data/spec/unit/forge/tar_spec.rb +9 -0
  36. data/spec/unit/forge/unpacker_spec.rb +58 -0
  37. data/spec/unit/forge/v3/base/paginated_collection_spec.rb +68 -46
  38. data/spec/unit/forge/v3/base_spec.rb +1 -1
  39. data/spec/unit/forge/v3/metadata_spec.rb +300 -0
  40. data/spec/unit/forge/v3/module_spec.rb +14 -36
  41. data/spec/unit/forge/v3/release_spec.rb +9 -30
  42. data/spec/unit/forge/v3/user_spec.rb +7 -7
  43. metadata +127 -41
  44. checksums.yaml +0 -7
  45. data/lib/puppet_forge/middleware/json_for_her.rb +0 -37
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "uri": "/v3/releases/puppetlabs-apache-0.0.1",
3
+ "slug": "puppetlabs-apache-0.0.1",
3
4
  "module": {
4
5
  "uri": "/v3/modules/puppetlabs-apache",
6
+ "slug": "puppetlabs-apache",
5
7
  "name": "apache",
6
8
  "owner": {
7
9
  "uri": "/v3/users/puppetlabs",
10
+ "slug": "puppetlabs",
8
11
  "username": "puppetlabs",
9
12
  "gravatar_id": "fdd009b7c1ec96e088b389f773e87aec"
10
13
  }
@@ -90,4 +93,4 @@
90
93
  "created_at": "2010-05-20 22:43:44 -0700",
91
94
  "updated_at": "2010-05-20 22:43:44 -0700",
92
95
  "deleted_at": null
93
- }
96
+ }
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+
3
+ describe PuppetForge::V3::Module do
4
+ before do
5
+
6
+ PuppetForge.host = "https://forge-aio01-petest.puppetlabs.com/"
7
+ PuppetForge::V3::Base.conn = PuppetForge::Connection.make_connection(PuppetForge.host, nil, {:ssl => {:verify => false} })
8
+ end
9
+
10
+ context "::find" do
11
+ context "gets information on an existing module and" do
12
+ let (:mod) { PuppetForge::V3::Module.find('puppetforgegemtesting-thorin') }
13
+
14
+ it "returns a PuppetForge::V3::Module." do
15
+ expect(mod).to be_a(PuppetForge::V3::Module)
16
+ end
17
+
18
+ it "exposes the API information." do
19
+ expect(mod).to respond_to(:uri)
20
+ expect(mod).to respond_to(:owner)
21
+ expect(mod).to respond_to(:current_release)
22
+ expect(mod).to respond_to(:releases)
23
+
24
+ expect(mod.uri).to be_a(String)
25
+ expect(mod.owner).to be_a(PuppetForge::V3::User)
26
+ expect(mod.current_release).to be_a(PuppetForge::V3::Release)
27
+ expect(mod.releases.first).to be_a(PuppetForge::V3::Release)
28
+ end
29
+
30
+ end
31
+
32
+ context "raises Faraday::ResourceNotFound when" do
33
+ let (:mod) { PuppetForge::V3::Module.find('puppetforgegemtesting-bilbo') }
34
+
35
+ it "the module does not exist" do
36
+ expect { mod }.to raise_error(Faraday::ResourceNotFound)
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+
43
+ context "::where" do
44
+ context "finds matching resources" do
45
+
46
+ it "only returns modules that match the query" do
47
+ modules = PuppetForge::V3::Module.where(:owner => 'puppetforgegemtesting')
48
+
49
+ expect(modules).to be_a(PuppetForge::V3::Base::PaginatedCollection)
50
+ modules.each do |mod|
51
+ expect(mod.owner.username).to eq('puppetforgegemtesting')
52
+ end
53
+
54
+ end
55
+
56
+ it "returns a paginated response" do
57
+ modules = PuppetForge::V3::Module.where(:owner => 'puppetforgegemtesting', :limit => 1)
58
+
59
+ expect(modules.limit).to eq(1)
60
+ expect(modules.total).to eq(2)
61
+
62
+ expect(modules.next).not_to be_nil
63
+ end
64
+
65
+ end
66
+
67
+ context "does not find matching resources" do
68
+ it "returns an empty PaginatedCollection" do
69
+ modules = PuppetForge::V3::Module.where(:owner => 'absentuser')
70
+
71
+ expect(modules).to be_a(PuppetForge::V3::Base::PaginatedCollection)
72
+
73
+ expect(modules.size).to eq(0)
74
+ expect(modules.empty?).to be(true)
75
+ end
76
+ end
77
+ end
78
+ end
79
+
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+
3
+ describe PuppetForge::V3::Release do
4
+ before do
5
+ PuppetForge.host = "https://forge-aio01-petest.puppetlabs.com/"
6
+ PuppetForge::V3::Base.conn = PuppetForge::Connection.make_connection(PuppetForge.host, nil, {:ssl => {:verify => false} })
7
+ end
8
+
9
+ context "#find" do
10
+ context "when the release exists," do
11
+
12
+ it "find returns a PuppetForge::V3::Release." do
13
+ release = PuppetForge::V3::Release.find('puppetforgegemtesting-thorin-0.0.1')
14
+
15
+ expect(release).to be_a(PuppetForge::V3::Release)
16
+ end
17
+
18
+ it "it exposes the API information." do
19
+ release = PuppetForge::V3::Release.find('puppetforgegemtesting-thorin-0.0.1')
20
+
21
+ expect(release).to respond_to(:uri)
22
+
23
+ expect(release.uri).to be_a(String)
24
+ end
25
+
26
+ end
27
+
28
+ context "when the release doesn't exist," do
29
+ let (:release) { PuppetForge::V3::Release.find('puppetforgegemtesting-bilbo-0.0.1') }
30
+
31
+ it "find returns nil." do
32
+ expect { release }.to raise_error(Faraday::ResourceNotFound)
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+
39
+ context "::where" do
40
+ context "finds matching resources" do
41
+
42
+ it "only returns releases that match the query" do
43
+ releases = PuppetForge::V3::Release.where(:module => 'puppetforgegemtesting-thorin')
44
+
45
+ expect(releases).to be_a(PuppetForge::V3::Base::PaginatedCollection)
46
+
47
+ expect(releases.first.version).to eq("0.0.2")
48
+ expect(releases[1].version).to eq("0.0.1")
49
+
50
+ end
51
+
52
+ it "returns a paginated response" do
53
+ releases = PuppetForge::V3::Release.where(:module => 'puppetforgegemtesting-thorin', :limit => 1)
54
+
55
+ expect(releases.limit).to eq(1)
56
+ expect(releases.total).to eq(2)
57
+
58
+ expect(releases.next).not_to be_nil
59
+ end
60
+
61
+ end
62
+
63
+ context "does not find matching resources" do
64
+ it "returns an empty PaginatedCollection" do
65
+ releases = PuppetForge::V3::Release.where(:module => 'puppetforgegemtesting-notamodule')
66
+
67
+ expect(releases).to be_a(PuppetForge::V3::Base::PaginatedCollection)
68
+
69
+ expect(releases.size).to eq(0)
70
+ expect(releases.empty?).to be(true)
71
+ end
72
+ end
73
+ end
74
+ end
75
+
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+
3
+ describe PuppetForge::V3::User do
4
+ before do
5
+ PuppetForge.host = "https://forge-aio01-petest.puppetlabs.com/"
6
+ PuppetForge::V3::Base.conn = PuppetForge::Connection.make_connection(PuppetForge.host, nil, {:ssl => {:verify => false} })
7
+ end
8
+
9
+ context "#find" do
10
+ context "when the user exists," do
11
+
12
+ it "find returns a PuppetForge::V3::User." do
13
+ user = PuppetForge::V3::User.find('puppetforgegemtesting')
14
+ expect(user).to be_a(PuppetForge::V3::User)
15
+ end
16
+
17
+ it "it exposes the API information." do
18
+ user = PuppetForge::V3::User.find('puppetforgegemtesting')
19
+
20
+ expect(user).to respond_to(:uri)
21
+ expect(user).to respond_to(:modules)
22
+
23
+ expect(user.uri).to be_a(String)
24
+ expect(user.modules).to be_a(PuppetForge::V3::Base::PaginatedCollection)
25
+ end
26
+
27
+ end
28
+
29
+ context "when the user doesn't exists," do
30
+ let (:user) { PuppetForge::V3::User.find('notauser') }
31
+
32
+ it "find returns nil." do
33
+ expect { user }.to raise_error(Faraday::ResourceNotFound)
34
+ end
35
+
36
+ end
37
+ end
38
+
39
+ context "::where" do
40
+ context "finds matching resources" do
41
+
42
+ it "returns sorted users" do
43
+ users = PuppetForge::V3::User.where(:sort_by => 'releases')
44
+
45
+ expect(users).to be_a(PuppetForge::V3::Base::PaginatedCollection)
46
+
47
+ previous_releases = users.first.release_count
48
+ users.each do |user|
49
+ expect(user.release_count).to be <= previous_releases
50
+ previous_releases = user.release_count
51
+ end
52
+
53
+ end
54
+
55
+ it "returns a paginated response" do
56
+ users = PuppetForge::V3::User.where(:limit => 1)
57
+
58
+ expect(users.limit).to eq(1)
59
+
60
+ 2.times do
61
+ expect(users).not_to be_nil
62
+ users = users.next
63
+ end
64
+ end
65
+
66
+ end
67
+
68
+ end
69
+ end
70
+
@@ -10,18 +10,25 @@ end
10
10
 
11
11
  require 'puppet_forge'
12
12
 
13
- module StubbingHer
13
+ module StubbingFaraday
14
+
14
15
  def stub_api_for(klass)
15
- klass.use_api begin
16
- Her::API.new :url => "http://api.example.com" do |c|
17
- c.use PuppetForge::Middleware::JSONForHer
18
- c.adapter(:test) { |s| yield(s) }
16
+ allow(klass).to receive(:conn) do
17
+ Faraday.new :url => "http://api.example.com" do |builder|
18
+ builder.use PuppetForge::Middleware::SymbolifyJson
19
+ builder.response(:json, :content_type => /\bjson$/)
20
+ builder.response(:raise_error)
21
+ builder.use(:connection_failure)
22
+
23
+ builder.adapter(:test) { |s| yield(s) }
19
24
  end
20
25
  end
26
+
27
+ stubs = Faraday::Adapter::Test::Stubs.new
21
28
  end
22
29
 
23
- def stub_fixture(api, method, path)
24
- api.send(method, path) do |env|
30
+ def stub_fixture(stubs, method, path)
31
+ stubs.send(method, path) do |env|
25
32
  load_fixture([ env[:url].path, env[:url].query ].compact.join('?'))
26
33
  end
27
34
  end
@@ -51,7 +58,7 @@ RSpec.configure do |config|
51
58
  config.run_all_when_everything_filtered = true
52
59
  config.filter_run :focus
53
60
 
54
- config.include StubbingHer
61
+ config.include StubbingFaraday
55
62
 
56
63
  # Run specs in random order to surface order dependencies. If you find an
57
64
  # order dependency and want to debug it, you can fix the order by providing
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ # The adapter NetHttp must be required before the SocketError (used below) is accessible
4
+ require 'faraday/adapter/net_http'
5
+
6
+ describe PuppetForge::Connection::ConnectionFailure do
7
+
8
+ subject do
9
+ Faraday.new('https://my-site.url/some-path') do |builder|
10
+ builder.use(:connection_failure)
11
+
12
+ builder.adapter :test do |stub|
13
+ stub.get('/connectfail') { raise Faraday::ConnectionFailed.new(SocketError.new("getaddrinfo: Name or service not known"), :hi) }
14
+ end
15
+ end
16
+ end
17
+
18
+ it "includes the base URL in the error message" do
19
+ expect {
20
+ subject.get('/connectfail')
21
+ }.to raise_error(Faraday::ConnectionFailed, "Unable to connect to https://my-site.url: getaddrinfo: Name or service not known")
22
+ end
23
+
24
+ it "includes the proxy host in the error message when set" do
25
+ subject.proxy('https://some-unreachable.proxy:3128')
26
+ expect {
27
+ subject.get('/connectfail')
28
+ }.to raise_error(Faraday::ConnectionFailed, "Unable to connect to https://my-site.url (using proxy https://some-unreachable.proxy:3128): getaddrinfo: Name or service not known")
29
+ end
30
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ describe PuppetForge::Connection do
4
+ before(:each) do
5
+ PuppetForge.host = "https://forgeapi.puppetlabs.com"
6
+ end
7
+
8
+ let(:test_conn) do
9
+ PuppetForge::Connection
10
+ end
11
+
12
+ describe 'creating a new connection' do
13
+
14
+ let(:faraday_stubs) { Faraday::Adapter::Test::Stubs.new }
15
+
16
+ subject { test_conn.make_connection('https://some.site/url', [:test, faraday_stubs]) }
17
+
18
+ it 'parses response bodies with a JSON content-type into a hash' do
19
+ faraday_stubs.get('/json') { [200, {'Content-Type' => 'application/json'}, '{"hello": "world"}'] }
20
+ expect(subject.get('/json').body).to eq(:hello => 'world')
21
+ end
22
+
23
+ it 'returns the response body as-is when the content-type is not JSON' do
24
+ faraday_stubs.get('/binary') { [200, {'Content-Type' => 'application/octet-stream'}, 'I am a big bucket of binary data'] }
25
+ expect(subject.get('/binary').body).to eq('I am a big bucket of binary data')
26
+ end
27
+
28
+ it 'raises errors when the request has an error status code' do
29
+ faraday_stubs.get('/error') { [503, {}, "The server caught fire and cannot service your request right now"] }
30
+
31
+ expect {
32
+ subject.get('/error')
33
+ }.to raise_error(Faraday::ClientError, "the server responded with status 503")
34
+ end
35
+
36
+ context 'when an authorization value is provided' do
37
+ before(:each) do
38
+ allow(described_class).to receive(:authorization).and_return("auth-test value")
39
+ end
40
+
41
+ it 'sets authorization header on requests' do
42
+ expect(subject.headers).to include(:authorization => "auth-test value")
43
+ end
44
+ end
45
+ end
46
+
47
+ describe 'creating a default connection' do
48
+ it 'creates a connection with the PuppetForge host' do
49
+ conn = test_conn.default_connection
50
+ expect(conn.url_prefix.to_s).to eq 'https://forgeapi.puppetlabs.com/'
51
+ end
52
+ end
53
+ end
@@ -1,14 +1,17 @@
1
1
  require 'spec_helper'
2
- require 'json'
3
2
 
4
- describe Her::LazyAccessors do
3
+ describe PuppetForge::LazyAccessors do
5
4
  let(:klass) do
6
- Class.new do
7
- include Her::Model
8
- include Her::LazyAccessors
5
+ class PuppetForge::V3::Thing < PuppetForge::V3::Base
9
6
 
10
- def request_path
11
- "/things/#{id}"
7
+ # Needed for #inspect
8
+ def uri
9
+ "/things/1"
10
+ end
11
+
12
+ # Needed for fetch
13
+ def slug
14
+ "1"
12
15
  end
13
16
 
14
17
  def standalone_method
@@ -30,9 +33,13 @@ describe Her::LazyAccessors do
30
33
  def remote_shadow
31
34
  "-#{super}-"
32
35
  end
36
+
33
37
  end
38
+
39
+ PuppetForge::V3::Thing
34
40
  end
35
41
 
42
+ let(:base_class) { PuppetForge::V3::Base }
36
43
  let(:local_data) { { :id => 1, :local => 'data', :shadow => 'x' } }
37
44
  let(:remote_data) { local_data.merge(:remote => 'DATA', :remote_shadow => 'X') }
38
45
 
@@ -80,9 +87,9 @@ describe Her::LazyAccessors do
80
87
 
81
88
  describe 'remote attributes' do
82
89
  before do
83
- stub_api_for(klass) do |api|
84
- api.get('/things/1') do
85
- [ 200, { 'Content-Type' => 'json' }, remote_data.to_json ]
90
+ stub_api_for(base_class) do |api|
91
+ api.get('/v3/things/1') do
92
+ [ 200, { 'Content-Type' => 'json' }, remote_data ]
86
93
  end
87
94
  end
88
95
  end
@@ -122,9 +129,9 @@ describe Her::LazyAccessors do
122
129
 
123
130
  describe 'unsatisfiable attributes' do
124
131
  before do
125
- stub_api_for(klass) do |api|
126
- api.get('/things/1') do
127
- [ 200, { 'Content-Type' => 'json' }, remote_data.to_json ]
132
+ stub_api_for(base_class) do |api|
133
+ api.get('/v3/things/1') do
134
+ [ 200, { 'Content-Type' => 'json' }, remote_data ]
128
135
  end
129
136
  end
130
137
  end
@@ -1,31 +1,32 @@
1
1
  require 'spec_helper'
2
- require 'json'
3
2
 
4
- describe Her::LazyRelations do
5
- let(:klass) do |*args|
6
- ctx = self
3
+ describe PuppetForge::LazyRelations do
4
+ class PuppetForge::V3::Parent < PuppetForge::V3::Base
7
5
 
8
- Class.new do
9
- include Her::Model
10
- include Her::LazyRelations
6
+ lazy :relation, 'Thing'
7
+ lazy :chained, 'Parent'
8
+ lazy_collection :relations, 'Thing'
9
+ lazy_collection :parents, 'Parent'
11
10
 
12
- lazy :relation, ctx.related_class
13
- lazy :chained, self
14
- lazy_collection :relations, ctx.related_class
15
- lazy_collection :parents, self
11
+ def uri
12
+ "/parents/#{slug}"
13
+ end
16
14
 
17
- def request_path
18
- "/parents/#{id}"
15
+ def slug
16
+ "1"
19
17
  end
20
18
  end
21
- end
22
19
 
23
- let(:related_class) do
24
- Class.new do
25
- include Her::Model
20
+ class PuppetForge::V3::Thing < PuppetForge::V3::Base
21
+
22
+ # Needed for #inspect
23
+ def uri
24
+ "/things/1"
25
+ end
26
26
 
27
- def request_path
28
- "/things/#{id}"
27
+ # Needed for fetch
28
+ def slug
29
+ "1"
29
30
  end
30
31
 
31
32
  def standalone_method
@@ -47,7 +48,16 @@ describe Her::LazyRelations do
47
48
  def remote_shadow
48
49
  "-#{super}-"
49
50
  end
51
+
50
52
  end
53
+
54
+ let(:base_class) { PuppetForge::V3::Base }
55
+ let(:klass) do |*args|
56
+ PuppetForge::V3::Parent
57
+ end
58
+
59
+ let(:related_class) do
60
+ PuppetForge::V3::Thing
51
61
  end
52
62
 
53
63
  let(:local_data) { { :id => 1, :local => 'data', :shadow => 'x' } }
@@ -56,7 +66,9 @@ describe Her::LazyRelations do
56
66
  describe '.lazy' do
57
67
  subject { klass.new(:relation => local_data).relation }
58
68
 
59
- it { should be_a(related_class) }
69
+ it do
70
+ should be_a(related_class)
71
+ end
60
72
 
61
73
  it 'does not call methods to #inspect' do
62
74
  expect(subject).not_to receive(:shadow)
@@ -94,9 +106,9 @@ describe Her::LazyRelations do
94
106
 
95
107
  describe 'remote attributes' do
96
108
  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 ]
109
+ stub_api_for(base_class) do |stubs|
110
+ stubs.get('/v3/things/1') do
111
+ [ 200, { 'Content-Type' => 'json' }, remote_data ]
100
112
  end
101
113
  end
102
114
  end
@@ -136,18 +148,17 @@ describe Her::LazyRelations do
136
148
 
137
149
  describe 'remote relations' do
138
150
  before do
139
- stub_api_for(klass) do |api|
140
- api.get('/parents/1') do
151
+ stub_api_for(base_class) do |api|
152
+ api.get('/v3/parents/1') do
141
153
  data = { :id => 1, :relation => local_data }
142
- [ 200, { 'Content-Type' => 'json' }, data.to_json ]
154
+ [ 200, { 'Content-Type' => 'json' }, data ]
143
155
  end
144
- end
145
156
 
146
- stub_api_for(related_class) do |api|
147
- api.get('/things/1') do
148
- [ 200, { 'Content-Type' => 'json' }, remote_data.to_json ]
157
+ api.get('/v3/things/1') do
158
+ [ 200, { 'Content-Type' => 'json' }, remote_data ]
149
159
  end
150
160
  end
161
+
151
162
  end
152
163
 
153
164
  subject { klass.new(:chained => { :id => 1 }) }
@@ -167,13 +178,15 @@ describe Her::LazyRelations do
167
178
 
168
179
  describe 'unsatisfiable attributes' do
169
180
  before do
170
- stub_api_for(klass) do |api|
171
- api.get('/things/1') do
172
- [ 200, { 'Content-Type' => 'json' }, remote_data.to_json ]
181
+ stub_api_for(base_class) do |api|
182
+ api.get('/v3/parents/1') do
183
+ [ 200, { 'Content-Type' => 'json' }, remote_data ]
173
184
  end
174
185
  end
175
186
  end
176
187
 
188
+ subject { klass.new(local_data) }
189
+
177
190
  example 'raise an exception when accessing an unknown attribute' do
178
191
  expect { subject.unknown_attribute }.to raise_error(NoMethodError)
179
192
  end
@@ -221,9 +234,9 @@ describe Her::LazyRelations do
221
234
 
222
235
  describe 'remote attributes' do
223
236
  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 ]
237
+ stub_api_for(base_class) do |api|
238
+ api.get('/v3/things/1') do
239
+ [ 200, { 'Content-Type' => 'json' }, remote_data ]
227
240
  end
228
241
  end
229
242
  end
@@ -263,18 +276,17 @@ describe Her::LazyRelations do
263
276
 
264
277
  describe 'remote relations' do
265
278
  before do
266
- stub_api_for(klass) do |api|
267
- api.get('/parents/1') do
279
+ stub_api_for(base_class) do |api|
280
+ api.get('/v3/parents/1') do
268
281
  data = { :id => 1, :parents => [{ :id => 1, :relation => local_data }] }
269
- [ 200, { 'Content-Type' => 'json' }, data.to_json ]
282
+ [ 200, { 'Content-Type' => 'json' }, data ]
270
283
  end
271
- end
272
284
 
273
- stub_api_for(related_class) do |api|
274
- api.get('/things/1') do
275
- [ 200, { 'Content-Type' => 'json' }, remote_data.to_json ]
285
+ api.get('/v3/things/1') do
286
+ [ 200, { 'Content-Type' => 'json' }, remote_data ]
276
287
  end
277
288
  end
289
+
278
290
  end
279
291
 
280
292
  subject { klass.new(:id => 1) }
@@ -294,13 +306,15 @@ describe Her::LazyRelations do
294
306
 
295
307
  describe 'unsatisfiable attributes' do
296
308
  before do
297
- stub_api_for(klass) do |api|
298
- api.get('/things/1') do
299
- [ 200, { 'Content-Type' => 'json' }, remote_data.to_json ]
309
+ stub_api_for(base_class) do |api|
310
+ api.get('/v3/parents/1') do
311
+ [ 200, { 'Content-Type' => 'json' }, remote_data ]
300
312
  end
301
313
  end
302
314
  end
303
315
 
316
+ subject { klass.new(local_data) }
317
+
304
318
  example 'raise an exception when accessing an unknown attribute' do
305
319
  expect { subject.unknown_attribute }.to raise_error(NoMethodError)
306
320
  end