frenetic 0.0.12 → 0.0.20.alpha.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.
Files changed (43) hide show
  1. data/.gitignore +1 -0
  2. data/.irbrc +3 -0
  3. data/.ruby-version +1 -0
  4. data/.travis.yml +0 -1
  5. data/Gemfile +1 -3
  6. data/README.md +138 -125
  7. data/frenetic.gemspec +5 -6
  8. data/lib/frenetic.rb +31 -43
  9. data/lib/frenetic/concerns/collection_rest_methods.rb +13 -0
  10. data/lib/frenetic/concerns/configurable.rb +59 -0
  11. data/lib/frenetic/concerns/hal_linked.rb +59 -0
  12. data/lib/frenetic/concerns/member_rest_methods.rb +15 -0
  13. data/lib/frenetic/concerns/structured.rb +53 -0
  14. data/lib/frenetic/configuration.rb +40 -76
  15. data/lib/frenetic/middleware/hal_json.rb +23 -0
  16. data/lib/frenetic/resource.rb +77 -62
  17. data/lib/frenetic/resource_collection.rb +46 -0
  18. data/lib/frenetic/version.rb +2 -2
  19. data/spec/concerns/configurable_spec.rb +50 -0
  20. data/spec/concerns/hal_linked_spec.rb +116 -0
  21. data/spec/concerns/member_rest_methods_spec.rb +41 -0
  22. data/spec/concerns/structured_spec.rb +214 -0
  23. data/spec/configuration_spec.rb +99 -0
  24. data/spec/fixtures/test_api_requests.rb +88 -0
  25. data/spec/frenetic_spec.rb +137 -0
  26. data/spec/middleware/hal_json_spec.rb +83 -0
  27. data/spec/resource_collection_spec.rb +80 -0
  28. data/spec/resource_spec.rb +211 -0
  29. data/spec/spec_helper.rb +4 -13
  30. data/spec/support/rspec.rb +5 -0
  31. data/spec/support/webmock.rb +3 -0
  32. metadata +59 -57
  33. data/.rvmrc +0 -1
  34. data/lib/frenetic/hal_json.rb +0 -23
  35. data/lib/frenetic/hal_json/response_wrapper.rb +0 -43
  36. data/lib/recursive_open_struct.rb +0 -79
  37. data/spec/fixtures/vcr_cassettes/description_error_unauthorized.yml +0 -36
  38. data/spec/fixtures/vcr_cassettes/description_success.yml +0 -38
  39. data/spec/lib/frenetic/configuration_spec.rb +0 -189
  40. data/spec/lib/frenetic/hal_json/response_wrapper_spec.rb +0 -70
  41. data/spec/lib/frenetic/hal_json_spec.rb +0 -68
  42. data/spec/lib/frenetic/resource_spec.rb +0 -182
  43. data/spec/lib/frenetic_spec.rb +0 -129
@@ -1,68 +0,0 @@
1
- describe Frenetic::HalJson do
2
- let(:hal_json) { described_class.new }
3
-
4
- let(:app_callbacks_stub) do
5
- double('FaradayCallbackStubs').tap do |cb|
6
- cb.stub(:on_complete).and_yield env
7
- end
8
- end
9
-
10
- let(:app_stub) do
11
- double('FaradayAppStub').tap do |app|
12
- app.stub(:call).and_return app_callbacks_stub
13
- end
14
- end
15
-
16
- before { hal_json.instance_variable_set '@app', app_stub }
17
-
18
- subject { hal_json }
19
-
20
- describe "#call" do
21
- let(:env) { { status:200 } }
22
-
23
- it "should execute the on_complete callback" do
24
- hal_json.should_receive( :on_complete ).with env
25
-
26
- hal_json.call env
27
- end
28
- end
29
-
30
- describe "#on_complete" do
31
- context "with a successful response" do
32
- let(:env) do
33
- {
34
- status:200,
35
- body: JSON.generate({
36
- '_links' => {}
37
- })
38
- }
39
- end
40
-
41
- before { hal_json.on_complete(env) }
42
-
43
- it "should parse the HAL+JSON response" do
44
- env[:body].should be_a( Frenetic::HalJson::ResponseWrapper )
45
- end
46
- end
47
- end
48
-
49
- describe "#success?" do
50
- subject { hal_json.success?( env ) }
51
-
52
- context "with a 200 OK response" do
53
- let(:env) { { status:200 } }
54
-
55
- it { should be_true }
56
- end
57
- context "with a 201 Created response" do
58
- let(:env) { { status:201 } }
59
-
60
- it { should be_true }
61
- end
62
- context "with a 204 No Content" do
63
- let(:env) { { status:204 } }
64
-
65
- it { should be_false }
66
- end
67
- end
68
- end
@@ -1,182 +0,0 @@
1
- describe Frenetic::Resource do
2
-
3
- let(:client) { Frenetic.new(url:'http://example.org') }
4
-
5
- let(:resource) { MyResource.new }
6
-
7
- let(:other_resource) { MyOtherResource.new }
8
-
9
- let(:description_stub) do
10
- Frenetic::HalJson::ResponseWrapper.new('resources' => {
11
- 'schema' => {
12
- 'my_resource' => { 'properties' => { 'foo' => 'string', 'baz' => 'integer' } },
13
- 'my_other_resource' => { 'properties' => { 'bar' => 'integer' } }
14
- } } )
15
- end
16
-
17
- before do
18
- client.stub(:description).and_return description_stub
19
-
20
- described_class.stub(:api).and_return client
21
-
22
- stub_const 'MyResource', Class.new(described_class)
23
- stub_const 'MyOtherResource', Class.new(described_class)
24
- end
25
-
26
- subject { resource }
27
-
28
- describe '#attributes' do
29
- subject { resource.attributes }
30
-
31
- it { should include 'foo' => nil }
32
- it { should include 'baz' => nil }
33
- end
34
-
35
- describe '#to_hash' do
36
- subject { resource.to_hash }
37
-
38
- it { should == resource.attributes }
39
- end
40
-
41
- context "created from a Hash" do
42
- let(:resource) { MyResource.new( foo: 'bar' ) }
43
-
44
- it { should respond_to(:foo) }
45
- it { should respond_to(:foo=) }
46
- its(:links) { should be_a Hash }
47
- its(:links) { should be_empty }
48
-
49
- context 'other subclasses' do
50
- subject { other_resource }
51
-
52
- it { should_not respond_to(:foo) }
53
- it { should_not respond_to(:foo=) }
54
- end
55
- end
56
-
57
- context "created from a HAL-JSON response" do
58
- let(:api_response) do
59
- {
60
- '_links' => {
61
- '_self' => { '_href' => 'bar' }
62
- },
63
- 'foo' => 1,
64
- 'bar' => 2
65
- }
66
- end
67
-
68
- let(:wrapped_response) do
69
- Frenetic::HalJson::ResponseWrapper.new(api_response)
70
- end
71
-
72
- let(:resource_a) { MyResource.new( wrapped_response ) }
73
-
74
- let(:resource_b) { MyResource.new }
75
-
76
- before do
77
- resource_a && resource_b
78
- end
79
-
80
- context "initialized with data" do
81
- subject { resource_a }
82
-
83
- its(:foo) { should == 1 }
84
- it { should_not respond_to(:bar) }
85
- its(:links) { should_not be_empty }
86
- end
87
-
88
- context "intiailized in sequence without data" do
89
- subject { resource_b }
90
-
91
- it { should respond_to(:foo) }
92
- it { should_not respond_to(:bar) }
93
- its(:links) { should be_empty }
94
- end
95
-
96
- context "with embedded resources" do
97
- let(:api_response) do
98
- {
99
- '_links' => {
100
- '_self' => { '_href' => 'bar' }
101
- },
102
- 'foo' => 1,
103
- '_embedded' => embed
104
- }
105
- end
106
-
107
- subject { resource_a }
108
-
109
- context 'that have a Resource representation' do
110
- subject { super().my_other_resource }
111
-
112
- let(:embed) do
113
- { 'my_other_resource' => { 'bar' => 123 } }
114
- end
115
-
116
- its(:bar) { should == 123 }
117
- end
118
-
119
- context 'that do not have a Resource representation' do
120
- subject { super().foo }
121
-
122
- let(:embed) do
123
- { 'foo' => { 'bar' => 'baz' } }
124
- end
125
-
126
- it { should include 'bar' => 'baz' }
127
- end
128
- end
129
- end
130
-
131
- describe ".api_client" do
132
- before do
133
- described_class.unstub! :api
134
- end
135
-
136
- subject { MyResource }
137
-
138
- context "with a block" do
139
- before { subject.api_client { client } }
140
-
141
- it "should reference the defined API client" do
142
- subject.api.should eq client
143
-
144
- MyOtherResource.should_not respond_to :api
145
- end
146
- end
147
-
148
- context "with an argument" do
149
- before { MyResource.api_client client }
150
-
151
- it "should reference the defined API client" do
152
- subject.api.should eq client
153
-
154
- MyOtherResource.should_not respond_to :api
155
- end
156
- end
157
- end
158
-
159
- describe ".schema" do
160
- subject { resource.class.schema }
161
-
162
- context "with a defined API Client" do
163
- before do
164
- client.stub(:description).and_return description_stub
165
-
166
- resource.class.api_client client
167
- end
168
-
169
- it "should return the schema for the specific resource" do
170
- subject.should == description_stub.resources.schema.my_resource.properties
171
- end
172
- end
173
-
174
- context "without a defined API Client" do
175
- before { described_class.stub(:respond_to?).with(:api).and_return false }
176
-
177
- it "should raise an error" do
178
- expect { subject }.to raise_error(Frenetic::MissingAPIReference)
179
- end
180
- end
181
- end
182
- end
@@ -1,129 +0,0 @@
1
- describe Frenetic do
2
- let(:config) do
3
- {
4
- url: 'http://example.org:5447/api',
5
- api_key: '1234567890',
6
- version: 'v1',
7
- response: {}
8
- }
9
- end
10
-
11
- let(:client) { described_class.new(config) }
12
-
13
- subject { client }
14
-
15
- it { should respond_to(:description) }
16
- it { should respond_to(:connection) }
17
- it { should respond_to(:conn) }
18
- it { should respond_to(:get) }
19
- it { should respond_to(:put) }
20
- it { should respond_to(:post) }
21
- it { should respond_to(:delete) }
22
-
23
- its(:connection) { should be_a(Faraday::Connection) }
24
-
25
- it 'should accept a configuration block' do
26
- described_class.new( config ) do |cfg|
27
- cfg.should be_a described_class::Configuration
28
- end
29
- end
30
-
31
- describe "#connection" do
32
- let(:connection) { client.connection }
33
-
34
- subject { client.connection }
35
-
36
- it { should be_a Faraday::Connection }
37
-
38
- it "should be created" do
39
- Faraday.should_receive( :new ).with do |cfg|
40
- cfg.has_key? :url
41
- end
42
-
43
- client
44
- end
45
-
46
- describe 'logger configuration' do
47
- before { config[:response][:use_logger] = true }
48
-
49
- subject { connection.builder.handlers.collect(&:name) }
50
-
51
- it { should include 'Faraday::Response::Logger' }
52
- end
53
-
54
- describe 'middleware initialization' do
55
- before { stub_const 'MyMiddleware', Class.new }
56
-
57
- let(:client) do
58
- described_class.new(config) do |cfg|
59
- cfg.use MyMiddleware, foo:123
60
- end
61
- end
62
-
63
- subject { connection.builder.handlers }
64
-
65
- it 'should add the middleware to the connection' do
66
- subject.should include MyMiddleware
67
- end
68
- end
69
-
70
- describe 'Faraday adapter' do
71
- subject { connection.builder.handlers }
72
-
73
- context 'by default' do
74
- it 'should be :patron' do
75
- subject.should include Faraday::Adapter::NetHttp
76
- end
77
- end
78
-
79
- context 'when explicitly set' do
80
- before do
81
- config.merge! adapter: :patron
82
- end
83
-
84
- it 'should use the specified adapter' do
85
- subject.should include Faraday::Adapter::Patron
86
- end
87
- end
88
- end
89
- end
90
-
91
- describe "#description" do
92
- context "for a conforming API" do
93
- subject do
94
- VCR.use_cassette('description_success') do
95
- client.description
96
- end
97
- end
98
-
99
- it { should be_a( Frenetic::HalJson::ResponseWrapper ) }
100
- end
101
-
102
- context "with an unauthorized request" do
103
- let(:fetch!) do
104
- VCR.use_cassette('description_error_unauthorized') do
105
- client.description
106
- end
107
- end
108
-
109
- it "should raise an error" do
110
- expect{ fetch! }.to raise_error(Frenetic::InvalidAPIDescription)
111
- end
112
- end
113
- end
114
-
115
- describe "#reload!" do
116
- before do
117
- VCR.use_cassette('description_success') do
118
- client.description
119
- end
120
-
121
- client.reload!
122
- end
123
-
124
- it "should not have any non-Nil instance variables" do
125
- client.instance_variables.none? { |s| client.instance_variable_get(s).nil? }.should be_false
126
- end
127
- end
128
-
129
- end