active_rest_client 0.9.58
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.simplecov +4 -0
- data/Gemfile +4 -0
- data/Guardfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +585 -0
- data/Rakefile +3 -0
- data/active_rest_client.gemspec +34 -0
- data/lib/active_rest_client.rb +23 -0
- data/lib/active_rest_client/base.rb +128 -0
- data/lib/active_rest_client/caching.rb +84 -0
- data/lib/active_rest_client/configuration.rb +69 -0
- data/lib/active_rest_client/connection.rb +76 -0
- data/lib/active_rest_client/connection_manager.rb +21 -0
- data/lib/active_rest_client/headers_list.rb +47 -0
- data/lib/active_rest_client/instrumentation.rb +62 -0
- data/lib/active_rest_client/lazy_association_loader.rb +95 -0
- data/lib/active_rest_client/lazy_loader.rb +23 -0
- data/lib/active_rest_client/logger.rb +67 -0
- data/lib/active_rest_client/mapping.rb +65 -0
- data/lib/active_rest_client/proxy_base.rb +143 -0
- data/lib/active_rest_client/recording.rb +24 -0
- data/lib/active_rest_client/request.rb +412 -0
- data/lib/active_rest_client/request_filtering.rb +52 -0
- data/lib/active_rest_client/result_iterator.rb +66 -0
- data/lib/active_rest_client/validation.rb +60 -0
- data/lib/active_rest_client/version.rb +3 -0
- data/spec/lib/base_spec.rb +245 -0
- data/spec/lib/caching_spec.rb +179 -0
- data/spec/lib/configuration_spec.rb +105 -0
- data/spec/lib/connection_manager_spec.rb +36 -0
- data/spec/lib/connection_spec.rb +73 -0
- data/spec/lib/headers_list_spec.rb +61 -0
- data/spec/lib/instrumentation_spec.rb +59 -0
- data/spec/lib/lazy_association_loader_spec.rb +118 -0
- data/spec/lib/lazy_loader_spec.rb +25 -0
- data/spec/lib/logger_spec.rb +63 -0
- data/spec/lib/mapping_spec.rb +48 -0
- data/spec/lib/proxy_spec.rb +154 -0
- data/spec/lib/recording_spec.rb +34 -0
- data/spec/lib/request_filtering_spec.rb +72 -0
- data/spec/lib/request_spec.rb +471 -0
- data/spec/lib/result_iterator_spec.rb +104 -0
- data/spec/lib/validation_spec.rb +113 -0
- data/spec/spec_helper.rb +22 -0
- metadata +265 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveRestClient::LazyLoader do
|
4
|
+
let(:request) { double("Request") }
|
5
|
+
let(:response) { double("Response") }
|
6
|
+
|
7
|
+
it "should not #call the passed in request during initialisation" do
|
8
|
+
request.should_not_receive(:call)
|
9
|
+
ActiveRestClient::LazyLoader.new(request)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should #call the passed in request if you check for response to a message" do
|
13
|
+
request.should_receive(:call)
|
14
|
+
loader = ActiveRestClient::LazyLoader.new(request)
|
15
|
+
loader.respond_to?(:each)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should #call the passed in request if you call a method and pass through the method" do
|
19
|
+
request.should_receive(:call).and_return(response)
|
20
|
+
response.should_receive(:valid).and_return(true)
|
21
|
+
loader = ActiveRestClient::LazyLoader.new(request)
|
22
|
+
expect(loader.valid).to be_true
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveRestClient::Instrumentation do
|
4
|
+
before :each do
|
5
|
+
ActiveRestClient::Logger.reset!
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should log things to the Rails logger if available" do
|
9
|
+
class Rails
|
10
|
+
class << self
|
11
|
+
attr_accessor :logger
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Rails.logger = double("Logger")
|
16
|
+
Rails.logger.should_receive(:debug)
|
17
|
+
Rails.logger.should_receive(:info)
|
18
|
+
Rails.logger.should_receive(:warn)
|
19
|
+
Rails.logger.should_receive(:error)
|
20
|
+
ActiveRestClient::Logger.debug("Hello world")
|
21
|
+
ActiveRestClient::Logger.info("Hello world")
|
22
|
+
ActiveRestClient::Logger.warn("Hello world")
|
23
|
+
ActiveRestClient::Logger.error("Hello world")
|
24
|
+
Object.send(:remove_const, :Rails)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should write to a logfile if one has been specified" do
|
28
|
+
ActiveRestClient::Logger.logfile = "/dev/null"
|
29
|
+
file = double('file')
|
30
|
+
File.should_receive(:open).with("/dev/null", "a").and_yield(file)
|
31
|
+
file.should_receive(:<<).with("Hello world")
|
32
|
+
ActiveRestClient::Logger.debug("Hello world")
|
33
|
+
|
34
|
+
file = double('file')
|
35
|
+
File.should_receive(:open).with("/dev/null", "a").and_yield(file)
|
36
|
+
file.should_receive(:<<).with("Hello info")
|
37
|
+
ActiveRestClient::Logger.info("Hello info")
|
38
|
+
|
39
|
+
file = double('file')
|
40
|
+
File.should_receive(:open).with("/dev/null", "a").and_yield(file)
|
41
|
+
file.should_receive(:<<).with("Hello error")
|
42
|
+
ActiveRestClient::Logger.error("Hello error")
|
43
|
+
|
44
|
+
file = double('file')
|
45
|
+
File.should_receive(:open).with("/dev/null", "a").and_yield(file)
|
46
|
+
file.should_receive(:<<).with("Hello warn")
|
47
|
+
ActiveRestClient::Logger.warn("Hello warn")
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should append to its own messages list if neither Rails nor a logfile has been specified" do
|
51
|
+
File.should_not_receive(:open)
|
52
|
+
ActiveRestClient::Logger.debug("Hello world")
|
53
|
+
ActiveRestClient::Logger.info("Hello info")
|
54
|
+
ActiveRestClient::Logger.warn("Hello warn")
|
55
|
+
ActiveRestClient::Logger.error("Hello error")
|
56
|
+
expect(ActiveRestClient::Logger.messages.size).to eq(4)
|
57
|
+
expect(ActiveRestClient::Logger.messages[0]).to eq("Hello world")
|
58
|
+
expect(ActiveRestClient::Logger.messages[1]).to eq("Hello info")
|
59
|
+
expect(ActiveRestClient::Logger.messages[2]).to eq("Hello warn")
|
60
|
+
expect(ActiveRestClient::Logger.messages[3]).to eq("Hello error")
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class MappingExampleBase
|
4
|
+
include ActiveRestClient::Mapping
|
5
|
+
end
|
6
|
+
|
7
|
+
class MappingExample < MappingExampleBase
|
8
|
+
get :test_get, "/get", tag:1, fake:"{result:true}", lazy:[:something]
|
9
|
+
put :test_put, "/put", tag:2
|
10
|
+
post :test_post, "/post", tag:3
|
11
|
+
delete :test_delete, "/delete", tag:4
|
12
|
+
end
|
13
|
+
|
14
|
+
describe ActiveRestClient::Mapping do
|
15
|
+
it "should support methods for get/put/post/delete for mapping" do
|
16
|
+
expect(EmptyExample).to respond_to(:get)
|
17
|
+
expect(EmptyExample).to respond_to(:put)
|
18
|
+
expect(EmptyExample).to respond_to(:post)
|
19
|
+
expect(EmptyExample).to respond_to(:delete)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should save URL for each mapped call" do
|
23
|
+
expect(MappingExample._calls[:test_get][:url]).to eq("/get")
|
24
|
+
expect(MappingExample._calls[:test_put][:url]).to eq("/put")
|
25
|
+
expect(MappingExample._calls[:test_post][:url]).to eq("/post")
|
26
|
+
expect(MappingExample._calls[:test_delete][:url]).to eq("/delete")
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should save the correct method type for each mapped call" do
|
30
|
+
expect(MappingExample._calls[:test_get][:method]).to eq(:get)
|
31
|
+
expect(MappingExample._calls[:test_put][:method]).to eq(:put)
|
32
|
+
expect(MappingExample._calls[:test_post][:method]).to eq(:post)
|
33
|
+
expect(MappingExample._calls[:test_delete][:method]).to eq(:delete)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should remember options set for each mapped call" do
|
37
|
+
expect(MappingExample._calls[:test_get][:options][:fake]).to eq("{result:true}")
|
38
|
+
expect(MappingExample._calls[:test_get][:options][:lazy]).to eq([:something])
|
39
|
+
expect(MappingExample._calls[:test_get][:options][:tag]).to eq(1)
|
40
|
+
expect(MappingExample._calls[:test_put][:options][:tag]).to eq(2)
|
41
|
+
expect(MappingExample._calls[:test_post][:options][:tag]).to eq(3)
|
42
|
+
expect(MappingExample._calls[:test_delete][:options][:tag]).to eq(4)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should allow for mapped calls on the class" do
|
46
|
+
expect(MappingExample).to respond_to(:test_get)
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'active_support/core_ext/hash'
|
3
|
+
|
4
|
+
class ProxyExample < ActiveRestClient::ProxyBase
|
5
|
+
get "/all" do
|
6
|
+
url.gsub!("/all", "/getAll")
|
7
|
+
passthrough
|
8
|
+
end
|
9
|
+
|
10
|
+
get "/old" do
|
11
|
+
url "/new"
|
12
|
+
passthrough
|
13
|
+
end
|
14
|
+
|
15
|
+
get "/list" do
|
16
|
+
get_params[:first_name] = get_params.delete(:fname)
|
17
|
+
get_params[:age] = 12
|
18
|
+
get_params.delete(:lname)
|
19
|
+
passthrough
|
20
|
+
end
|
21
|
+
|
22
|
+
post "/create" do
|
23
|
+
post_params[:first_name] = post_params.delete(:fname)
|
24
|
+
post_params[:age] = 12
|
25
|
+
post_params.delete(:lname)
|
26
|
+
passthrough
|
27
|
+
end
|
28
|
+
|
29
|
+
put "/update" do
|
30
|
+
body "MY-BODY-CONTENT"
|
31
|
+
passthrough
|
32
|
+
end
|
33
|
+
|
34
|
+
delete '/remove' do
|
35
|
+
passthrough
|
36
|
+
end
|
37
|
+
|
38
|
+
get "/change-format" do
|
39
|
+
response = passthrough
|
40
|
+
translate(response) do |body|
|
41
|
+
body["first_name"] = body.delete("fname")
|
42
|
+
body
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
get "/hal_test/:id" do
|
47
|
+
response = passthrough
|
48
|
+
translate(response) do |body|
|
49
|
+
body["_links"] = {"test" => {href:"/this/is/a/test"}}
|
50
|
+
body
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
get "/param/:id/:name" do
|
55
|
+
render "{\"id\":\"#{params[:id]}\", \"name\":\"#{params[:name]}\"}"
|
56
|
+
end
|
57
|
+
|
58
|
+
get "/fake" do
|
59
|
+
render "{\"id\":1234}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class ProxyClientExample < ActiveRestClient::Base
|
64
|
+
proxy ProxyExample
|
65
|
+
base_url "http://www.example.com"
|
66
|
+
|
67
|
+
get :all, "/all"
|
68
|
+
get :old, "/old"
|
69
|
+
get :list, "/list"
|
70
|
+
get :fake, "/fake"
|
71
|
+
get :param, "/param/:id/:name"
|
72
|
+
get :change_format, "/change-format"
|
73
|
+
post :create, "/create"
|
74
|
+
put :update, "/update"
|
75
|
+
get :not_proxied, "/not_proxied"
|
76
|
+
delete :remove, "/remove"
|
77
|
+
get :hal_test, "/hal_test/:id"
|
78
|
+
end
|
79
|
+
|
80
|
+
describe ActiveRestClient::Base do
|
81
|
+
it "allows the URL to be changed" do
|
82
|
+
ActiveRestClient::Connection.any_instance.should_receive(:get).with("/getAll?id=1", instance_of(Hash)).and_return(OpenStruct.new(body:"{\"result\":true}", status:200, headers:{}))
|
83
|
+
ProxyClientExample.all(id:1)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "allows the URL to be replaced" do
|
87
|
+
ActiveRestClient::Connection.any_instance.should_receive(:get).with("/new", instance_of(Hash)).and_return(OpenStruct.new(body:"{\"result\":true}", status:200, headers:{}))
|
88
|
+
ProxyClientExample.old
|
89
|
+
end
|
90
|
+
|
91
|
+
it "has access to the GET params and allow them to be changed/removed/added" do
|
92
|
+
ActiveRestClient::Connection.any_instance.should_receive(:get).with("/list?age=12&first_name=John", instance_of(Hash)).and_return(OpenStruct.new(body:"{\"result\":true}", status:200, headers:{}))
|
93
|
+
ProxyClientExample.list(fname:"John", lname:"Smith")
|
94
|
+
end
|
95
|
+
|
96
|
+
it "has access to the POST params and allow them to be changed/removed/added" do
|
97
|
+
ActiveRestClient::Connection.any_instance.should_receive(:post).with("/create", {age:12, first_name:"John"}.to_query, instance_of(Hash)).and_return(OpenStruct.new(body:"{\"result\":true}", status:200, headers:{}))
|
98
|
+
ProxyClientExample.create(fname:"John", lname:"Smith")
|
99
|
+
end
|
100
|
+
|
101
|
+
it "has access to raw body content for requests" do
|
102
|
+
ActiveRestClient::Connection.any_instance.should_receive(:put).with("/update", "MY-BODY-CONTENT", instance_of(Hash)).and_return(OpenStruct.new(body:"{\"result\":true}", status:200, headers:{}))
|
103
|
+
ProxyClientExample.update(fname:"John", lname:"Smith")
|
104
|
+
end
|
105
|
+
|
106
|
+
it "handles DELETE requests" do
|
107
|
+
ActiveRestClient::Connection.any_instance.should_receive(:delete).with("/remove", instance_of(Hash)).and_return(OpenStruct.new(body:"{\"result\":true}", status:200, headers:{}))
|
108
|
+
ProxyClientExample.remove
|
109
|
+
end
|
110
|
+
|
111
|
+
it "can return fake JSON data and have this parsed in the normal way" do
|
112
|
+
ActiveRestClient::Connection.any_instance.should_not_receive(:get).with("/fake", instance_of(Hash))
|
113
|
+
ret = ProxyClientExample.fake
|
114
|
+
expect(ret.id).to eq(1234)
|
115
|
+
end
|
116
|
+
|
117
|
+
it "can intercept the response and parse the response, alter it and pass it on during the request" do
|
118
|
+
ActiveRestClient::Connection.any_instance.should_receive(:get).with("/change-format", instance_of(Hash)).and_return(OpenStruct.new(body:"{\"fname\":\"Billy\"}", status:200, headers:{}))
|
119
|
+
ret = ProxyClientExample.change_format
|
120
|
+
expect(ret.first_name).to eq("Billy")
|
121
|
+
end
|
122
|
+
|
123
|
+
it "can continue with the request in the normal way, passing it on to the server" do
|
124
|
+
ActiveRestClient::Connection.any_instance.should_receive(:get).with("/not_proxied?id=1", instance_of(Hash)).and_return(OpenStruct.new(body:"{\"result\":true}", status:200, headers:{}))
|
125
|
+
ProxyClientExample.not_proxied(id:1)
|
126
|
+
end
|
127
|
+
|
128
|
+
it "caches responses in the standard way" do
|
129
|
+
cache_store = double("CacheStore")
|
130
|
+
cache_store.stub(:read).with(any_args).and_return(nil)
|
131
|
+
ActiveRestClient::Base.stub(:cache_store).and_return(cache_store)
|
132
|
+
expiry = 10.minutes.from_now.rfc2822
|
133
|
+
ActiveRestClient::Connection.any_instance.should_receive(:put).with("/update", "MY-BODY-CONTENT", instance_of(Hash)).and_return(OpenStruct.new(body:"{\"result\":true}", status:200, headers:{"Expires" => expiry, "ETag" => "123456"}))
|
134
|
+
ActiveRestClient::Base.cache_store.should_receive(:write) do |key, object, options|
|
135
|
+
expect(key).to eq("ProxyClientExample:/update")
|
136
|
+
expect(object.etag).to eq("123456")
|
137
|
+
expect(object.expires).to eq(expiry)
|
138
|
+
end
|
139
|
+
ProxyClientExample.update(id:1)
|
140
|
+
end
|
141
|
+
|
142
|
+
it "can have parameters in the URL" do
|
143
|
+
ret = ProxyClientExample.param(id:1234, name:"Johnny")
|
144
|
+
expect(ret.id).to eq("1234")
|
145
|
+
expect(ret.name).to eq("Johnny")
|
146
|
+
end
|
147
|
+
|
148
|
+
it "can force the URL from a filter without it being passed through URL replacement" do
|
149
|
+
ActiveRestClient::Connection.any_instance.should_receive(:get).with("/hal_test/1", instance_of(Hash)).and_return(OpenStruct.new(body:"{\"result\":true}", status:200, headers:{}))
|
150
|
+
ActiveRestClient::Connection.any_instance.should_receive(:get).with("/this/is/a/test", instance_of(Hash)).and_return(OpenStruct.new(body:"{\"result\":true}", status:200, headers:{}))
|
151
|
+
expect(ProxyClientExample.hal_test(id:1).test.result).to eq(true)
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveRestClient::Recording do
|
4
|
+
it "can confirm if a recording callback is set" do
|
5
|
+
class MyObject1
|
6
|
+
include ActiveRestClient::Recording
|
7
|
+
end
|
8
|
+
expect(MyObject1.record_response?).to be_false
|
9
|
+
MyObject1.record_response do
|
10
|
+
puts "Hello world"
|
11
|
+
end
|
12
|
+
expect(MyObject1.record_response?).to be_true
|
13
|
+
end
|
14
|
+
|
15
|
+
it "remembers a block given to it to later be called back" do
|
16
|
+
class MyObject2
|
17
|
+
include ActiveRestClient::Recording
|
18
|
+
end
|
19
|
+
MyObject2.record_response do
|
20
|
+
puts "Hello world"
|
21
|
+
end
|
22
|
+
expect(MyObject2.instance_variable_get(:@record_response)).to_not be_nil
|
23
|
+
end
|
24
|
+
|
25
|
+
it "calls back to the block if record_response is given a url and response" do
|
26
|
+
class MyObject3
|
27
|
+
include ActiveRestClient::Recording
|
28
|
+
end
|
29
|
+
MyObject3.record_response do |url, response|
|
30
|
+
raise Exception.new("#{url}|#{response}")
|
31
|
+
end
|
32
|
+
expect{MyObject3.record_response("http://www.example.com/", "Hello world")}.to raise_error(Exception, 'http://www.example.com/|Hello world')
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class RequestFilteringExample
|
4
|
+
include ActiveRestClient::RequestFiltering
|
5
|
+
|
6
|
+
before_request do |name, request|
|
7
|
+
request.get_params[:filter1] = "Hello"
|
8
|
+
end
|
9
|
+
|
10
|
+
before_request do |name, request|
|
11
|
+
request.post_params[:post_filter1] = "World"
|
12
|
+
end
|
13
|
+
|
14
|
+
before_request do |name, request|
|
15
|
+
request.headers["X-My-Header"] = "myvalue"
|
16
|
+
end
|
17
|
+
|
18
|
+
before_request :set_to_ssl
|
19
|
+
before_request :set_via_instance
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def self.set_to_ssl(name, request)
|
24
|
+
request.url.gsub!("http://", "https://")
|
25
|
+
end
|
26
|
+
|
27
|
+
def set_via_instance(name, request)
|
28
|
+
request.url.gsub!("//www", "//new")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class SubClassedRequestFilteringExample < RequestFilteringExample
|
33
|
+
before_request do |name, request|
|
34
|
+
request.get_params[:api_key] = 1234
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe ActiveRestClient::RequestFiltering do
|
39
|
+
let(:request) { OpenStruct.new(get_params:{}, post_params:{}, url:"http://www.example.com", headers:ActiveRestClient::HeadersList.new) }
|
40
|
+
|
41
|
+
it "should call through to adjust the parameters" do
|
42
|
+
RequestFilteringExample._filter_request(:test, request)
|
43
|
+
expect(request.get_params).to have_key(:filter1)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should call through for more than one filter" do
|
47
|
+
RequestFilteringExample._filter_request(:test, request)
|
48
|
+
expect(request.get_params).to have_key(:filter1)
|
49
|
+
expect(request.post_params).to have_key(:post_filter1)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should allow adjusting the URL via a named filter" do
|
53
|
+
RequestFilteringExample._filter_request(:test, request)
|
54
|
+
expect(request.url).to match(/https:\/\//)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should allow adjusting the URL via a named filter as an instance method" do
|
58
|
+
RequestFilteringExample._filter_request(:test, request)
|
59
|
+
expect(request.url).to match(/\/\/new\./)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should allow filters to be set on the parent or on the child" do
|
63
|
+
SubClassedRequestFilteringExample._filter_request(:test, request)
|
64
|
+
expect(request.url).to match(/\/\/new\./)
|
65
|
+
expect(request.get_params[:api_key]).to eq(1234)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should allow filters to add custom headers" do
|
69
|
+
RequestFilteringExample._filter_request(:test, request)
|
70
|
+
expect(request.headers["X-My-Header"]).to eq("myvalue")
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,471 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveRestClient::Request do
|
4
|
+
before :each do
|
5
|
+
class ExampleOtherClient < ActiveRestClient::Base ; end
|
6
|
+
class ExampleClient < ActiveRestClient::Base
|
7
|
+
base_url "http://www.example.com"
|
8
|
+
|
9
|
+
before_request do |name, request|
|
10
|
+
if request.method[:name] == :headers
|
11
|
+
request.headers["X-My-Header"] = "myvalue"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
get :all, "/", :has_many => {:expenses => ExampleOtherClient}
|
16
|
+
get :babies, "/babies", :has_many => {:children => ExampleOtherClient}
|
17
|
+
get :headers, "/headers"
|
18
|
+
get :find, "/:id"
|
19
|
+
post :create, "/create"
|
20
|
+
put :update, "/put/:id"
|
21
|
+
delete :remove, "/remove/:id"
|
22
|
+
get :hal, "/hal", fake:"{\"_links\":{\"child\": {\"href\": \"/child/1\"}, \"other\": {\"href\": \"/other/1\"}, \"cars\":[{\"href\": \"/car/1\", \"name\":\"car1\"}, {\"href\": \"/car/2\", \"name\":\"car2\"}, {\"href\": \"/car/not-embed\", \"name\":\"car_not_embed\"} ], \"lazy\": {\"href\": \"/lazy/load\"}, \"invalid\": [{\"href\": \"/invalid/1\"}]}, \"_embedded\":{\"other\":{\"name\":\"Jane\"},\"child\":{\"name\":\"Billy\"}, \"cars\":[{\"_links\": {\"self\": {\"href\": \"/car/1\"} }, \"make\": \"Bugatti\", \"model\": \"Veyron\"}, {\"_links\": {\"self\": {\"href\": \"/car/2\"} }, \"make\": \"Ferrari\", \"model\": \"F458 Italia\"} ], \"invalid\": [{\"present\":true, \"_links\": {} } ] } }", has_many:{other:ExampleOtherClient}
|
23
|
+
get :fake, "/fake", fake:"{\"result\":true, \"list\":[1,2,3,{\"test\":true}], \"child\":{\"grandchild\":{\"test\":true}}}"
|
24
|
+
get :defaults, "/defaults", defaults:{overwrite:"no", persist:"yes"}
|
25
|
+
end
|
26
|
+
|
27
|
+
class LazyLoadedExampleClient < ExampleClient
|
28
|
+
lazy_load!
|
29
|
+
get :fake, "/fake", fake:"{\"result\":true, \"list\":[1,2,3,{\"test\":true}], \"child\":{\"grandchild\":{\"test\":true}}}"
|
30
|
+
get :lazy_test, "/does-not-matter", fake:"{\"people\":[\"http://www.example.com/some/url\"]}", :lazy => %i{people}
|
31
|
+
end
|
32
|
+
|
33
|
+
class VerboseExampleClient < ExampleClient
|
34
|
+
verbose!
|
35
|
+
get :all, "/all"
|
36
|
+
end
|
37
|
+
|
38
|
+
class FilteredBodyExampleClient < ExampleClient
|
39
|
+
base_url "http://www.example.com"
|
40
|
+
before_request do |name, request|
|
41
|
+
request.body = Oj.dump(request.post_params)
|
42
|
+
end
|
43
|
+
|
44
|
+
post :save, "/save"
|
45
|
+
end
|
46
|
+
|
47
|
+
ActiveRestClient::Request.any_instance.stub(:read_cached_response)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should get an HTTP connection when called" do
|
51
|
+
connection = double(ActiveRestClient::Connection).as_null_object
|
52
|
+
ActiveRestClient::ConnectionManager.should_receive(:get_connection).and_return(connection)
|
53
|
+
connection.should_receive(:get).with("/", an_instance_of(Hash)).and_return(OpenStruct.new(body:'{"result":true}', headers:{}))
|
54
|
+
ExampleClient.all
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should get an HTTP connection when called and call get on it" do
|
58
|
+
ActiveRestClient::Connection.any_instance.should_receive(:get).with("/", an_instance_of(Hash)).and_return(OpenStruct.new(body:'{"result":true}', headers:{}))
|
59
|
+
ExampleClient.all
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should get an HTTP connection when called and call delete on it" do
|
63
|
+
ActiveRestClient::Connection.any_instance.should_receive(:delete).with("/remove/1", an_instance_of(Hash)).and_return(OpenStruct.new(body:'{"result":true}', headers:{}))
|
64
|
+
ExampleClient.remove(id:1)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should pass through get parameters" do
|
68
|
+
ActiveRestClient::Connection.any_instance.should_receive(:get).with("/?debug=true", an_instance_of(Hash)).and_return(OpenStruct.new(body:'{"result":true}', headers:{}))
|
69
|
+
ExampleClient.all debug:true
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should pass through get parameters, using defaults specified" do
|
73
|
+
ActiveRestClient::Connection.any_instance.should_receive(:get).with("/defaults?overwrite=yes&persist=yes", an_instance_of(Hash)).and_return(OpenStruct.new(body:'{"result":true}', headers:{}))
|
74
|
+
ExampleClient.defaults overwrite:"yes"
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should pass through url parameters" do
|
78
|
+
ActiveRestClient::Connection.any_instance.should_receive(:get).with("/1234", an_instance_of(Hash)).and_return(OpenStruct.new(body:'{"result":true}', headers:{}))
|
79
|
+
ExampleClient.find id:1234
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should accept an integer as the only parameter and use it as id" do
|
83
|
+
ActiveRestClient::Connection.any_instance.should_receive(:get).with("/1234", an_instance_of(Hash)).and_return(OpenStruct.new(body:'{"result":true}', headers:{}))
|
84
|
+
ExampleClient.find(1234)
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should accept a string as the only parameter and use it as id" do
|
88
|
+
ActiveRestClient::Connection.any_instance.should_receive(:get).with("/1234", an_instance_of(Hash)).and_return(OpenStruct.new(body:'{"result":true}', headers:{}))
|
89
|
+
ExampleClient.find("1234")
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should pass through url parameters and get parameters" do
|
93
|
+
ActiveRestClient::Connection.any_instance.should_receive(:get).with("/1234?debug=true", an_instance_of(Hash)).and_return(OpenStruct.new(body:"{\"result\":true}", headers:{}))
|
94
|
+
ExampleClient.find id:1234, debug:true
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should pass through url parameters and put parameters" do
|
98
|
+
ActiveRestClient::Connection.any_instance.should_receive(:put).with("/put/1234", "debug=true", an_instance_of(Hash)).and_return(OpenStruct.new(body:"{\"result\":true}", headers:{}))
|
99
|
+
ExampleClient.update id:1234, debug:true
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should pass through custom headers" do
|
103
|
+
ActiveRestClient::Connection.any_instance.should_receive(:get).with("/headers", hash_including("X-My-Header" => "myvalue")).and_return(OpenStruct.new(body:'{"result":true}', headers:{}))
|
104
|
+
ExampleClient.headers
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should parse JSON to give a nice object" do
|
108
|
+
ActiveRestClient::Connection.any_instance.should_receive(:put).with("/put/1234", "debug=true", an_instance_of(Hash)).and_return(OpenStruct.new(body:"{\"result\":true, \"list\":[1,2,3,{\"test\":true}], \"created_at\":\"2012-03-04T01:02:03Z\", \"child\":{\"grandchild\":{\"test\":true}}}", headers:{}))
|
109
|
+
object = ExampleClient.update id:1234, debug:true
|
110
|
+
expect(object.result).to eq(true)
|
111
|
+
expect(object.list.first).to eq(1)
|
112
|
+
expect(object.list.last.test).to eq(true)
|
113
|
+
expect(object.created_at).to be_an_instance_of(DateTime)
|
114
|
+
expect(object.child.grandchild.test).to eq(true)
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should parse JSON and return a nice object for faked responses" do
|
118
|
+
object = ExampleClient.fake id:1234, debug:true
|
119
|
+
expect(object.result).to eq(true)
|
120
|
+
expect(object.list.first).to eq(1)
|
121
|
+
expect(object.list.last.test).to eq(true)
|
122
|
+
expect(object.child.grandchild.test).to eq(true)
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should return a lazy loader object if lazy loading is enabled" do
|
126
|
+
object = LazyLoadedExampleClient.fake id:1234, debug:true
|
127
|
+
expect(object).to be_an_instance_of(ActiveRestClient::LazyLoader)
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should proxy through nice object for lazy loaded responses" do
|
131
|
+
object = LazyLoadedExampleClient.fake id:1234, debug:true
|
132
|
+
expect(object.result).to eq(true)
|
133
|
+
expect(object.list.first).to eq(1)
|
134
|
+
expect(object.list.last.test).to eq(true)
|
135
|
+
expect(object.child.grandchild.test).to eq(true)
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should return a LazyAssociationLoader for lazy loaded properties" do
|
139
|
+
object = LazyLoadedExampleClient.lazy_test
|
140
|
+
expect(object.people.size).to eq(1)
|
141
|
+
expect(object.people).to be_an_instance_of(ActiveRestClient::LazyAssociationLoader)
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should log faked responses" do
|
145
|
+
ActiveRestClient::Logger.stub(:debug)
|
146
|
+
ActiveRestClient::Logger.should_receive(:debug).with {|*args| args.first["Faked response found"]}
|
147
|
+
object = ExampleClient.fake id:1234, debug:true
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should parse an array within JSON to be a result iterator" do
|
151
|
+
ActiveRestClient::Connection.any_instance.should_receive(:put).with("/put/1234", "debug=true", an_instance_of(Hash)).and_return(OpenStruct.new(body:"[{\"first_name\":\"Johnny\"}, {\"first_name\":\"Billy\"}]", status:200, headers:{}))
|
152
|
+
object = ExampleClient.update id:1234, debug:true
|
153
|
+
expect(object).to be_instance_of(ActiveRestClient::ResultIterator)
|
154
|
+
expect(object.first.first_name).to eq("Johnny")
|
155
|
+
expect(object[1].first_name).to eq("Billy")
|
156
|
+
expect(object._status).to eq(200)
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should instantiate other classes using has_many when required to do so" do
|
160
|
+
ActiveRestClient::Connection.any_instance.should_receive(:get).with("/", an_instance_of(Hash)).and_return(OpenStruct.new(body:"{\"first_name\":\"Johnny\", \"expenses\":[{\"amount\":1}, {\"amount\":2}]}", status:200, headers:{}))
|
161
|
+
object = ExampleClient.all
|
162
|
+
expect(object.expenses.first).to be_instance_of(ExampleOtherClient)
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should instantiate other classes using has_many even if nested off the root" do
|
166
|
+
ActiveRestClient::Connection.any_instance.should_receive(:get).with("/babies", an_instance_of(Hash)).and_return(OpenStruct.new(body:"{\"first_name\":\"Johnny\", \"children\":{\"eldest\":[{\"name\":\"Billy\"}]}}", status:200, headers:{}))
|
167
|
+
object = ExampleClient.babies
|
168
|
+
expect(object.children.eldest.first).to be_instance_of(ExampleOtherClient)
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should assign new attributes to the existing object if possible" do
|
172
|
+
ActiveRestClient::Connection.
|
173
|
+
any_instance.
|
174
|
+
should_receive(:post).
|
175
|
+
with("/create", "first_name=John&should_disappear=true", an_instance_of(Hash)).
|
176
|
+
and_return(OpenStruct.new(body:"{\"first_name\":\"John\", \"id\":1234}", headers:{}))
|
177
|
+
object = ExampleClient.new(first_name:"John", should_disappear:true)
|
178
|
+
object.create
|
179
|
+
expect(object.first_name).to eq("John")
|
180
|
+
expect(object.should_disappear).to eq(nil)
|
181
|
+
expect(object.id).to eq(1234)
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should clearly pass through 200 status responses" do
|
185
|
+
ActiveRestClient::Connection.
|
186
|
+
any_instance.
|
187
|
+
should_receive(:post).
|
188
|
+
with("/create", "first_name=John&should_disappear=true", an_instance_of(Hash)).
|
189
|
+
and_return(OpenStruct.new(body:"{\"first_name\":\"John\", \"id\":1234}", headers:{}, status:200))
|
190
|
+
ActiveRestClient::Logger.should_receive(:info).with {|*args| args.first[%r{Requesting http://www.example.com/create}]}
|
191
|
+
ActiveRestClient::Logger.should_receive(:debug).with {|*args| args.first[/Response received \d+ bytes/]}
|
192
|
+
|
193
|
+
object = ExampleClient.new(first_name:"John", should_disappear:true)
|
194
|
+
object.create
|
195
|
+
expect(object._status).to eq(200)
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should debug log 200 responses" do
|
199
|
+
ActiveRestClient::Connection.
|
200
|
+
any_instance.
|
201
|
+
should_receive(:post).
|
202
|
+
with("/create", "first_name=John&should_disappear=true", an_instance_of(Hash)).
|
203
|
+
and_return(OpenStruct.new(body:"{\"first_name\":\"John\", \"id\":1234}", headers:{}, status:200))
|
204
|
+
ActiveRestClient::Logger.should_receive(:info).with {|*args| args.first[%r{Requesting http://www.example.com/create}]}
|
205
|
+
ActiveRestClient::Logger.should_receive(:debug).with {|*args| args.first[/Response received \d+ bytes/]}
|
206
|
+
|
207
|
+
object = ExampleClient.new(first_name:"John", should_disappear:true)
|
208
|
+
object.create
|
209
|
+
end
|
210
|
+
|
211
|
+
it "should verbose log if enabled" do
|
212
|
+
connection = double(ActiveRestClient::Connection).as_null_object
|
213
|
+
ActiveRestClient::ConnectionManager.should_receive(:get_connection).and_return(connection)
|
214
|
+
connection.should_receive(:get).with("/all", an_instance_of(Hash)).and_return(OpenStruct.new(body:'{"result":true}', headers:{"Content-Type" => "application/json", "Connection" => "close"}))
|
215
|
+
ActiveRestClient::Logger.should_receive(:debug).with("ActiveRestClient Verbose Log:")
|
216
|
+
ActiveRestClient::Logger.should_receive(:debug).with(/ > /).at_least(:twice)
|
217
|
+
ActiveRestClient::Logger.should_receive(:debug).with(/ < /).at_least(:twice)
|
218
|
+
ActiveRestClient::Logger.stub(:debug).with(any_args)
|
219
|
+
VerboseExampleClient.all
|
220
|
+
end
|
221
|
+
|
222
|
+
it "should raise an unauthorised exception for 401 errors" do
|
223
|
+
ActiveRestClient::Connection.
|
224
|
+
any_instance.
|
225
|
+
should_receive(:post).
|
226
|
+
with("/create", "first_name=John&should_disappear=true", an_instance_of(Hash)).
|
227
|
+
and_return(OpenStruct.new(body:"{\"first_name\":\"John\", \"id\":1234}", headers:{}, status:401))
|
228
|
+
object = ExampleClient.new(first_name:"John", should_disappear:true)
|
229
|
+
begin
|
230
|
+
object.create
|
231
|
+
rescue ActiveRestClient::HTTPUnauthorisedClientException => e
|
232
|
+
e
|
233
|
+
end
|
234
|
+
expect(e).to be_instance_of(ActiveRestClient::HTTPUnauthorisedClientException)
|
235
|
+
expect(e.status).to eq(401)
|
236
|
+
expect(e.result.first_name).to eq("John")
|
237
|
+
end
|
238
|
+
|
239
|
+
it "should raise a forbidden client exception for 403 errors" do
|
240
|
+
ActiveRestClient::Connection.
|
241
|
+
any_instance.
|
242
|
+
should_receive(:post).
|
243
|
+
with("/create", "first_name=John&should_disappear=true", an_instance_of(Hash)).
|
244
|
+
and_return(OpenStruct.new(body:"{\"first_name\":\"John\", \"id\":1234}", headers:{}, status:403))
|
245
|
+
object = ExampleClient.new(first_name:"John", should_disappear:true)
|
246
|
+
begin
|
247
|
+
object.create
|
248
|
+
rescue ActiveRestClient::HTTPForbiddenClientException => e
|
249
|
+
e
|
250
|
+
end
|
251
|
+
expect(e).to be_instance_of(ActiveRestClient::HTTPForbiddenClientException)
|
252
|
+
expect(e.status).to eq(403)
|
253
|
+
expect(e.result.first_name).to eq("John")
|
254
|
+
end
|
255
|
+
|
256
|
+
it "should raise a not found client exception for 404 errors" do
|
257
|
+
ActiveRestClient::Connection.
|
258
|
+
any_instance.
|
259
|
+
should_receive(:post).
|
260
|
+
with("/create", "first_name=John&should_disappear=true", an_instance_of(Hash)).
|
261
|
+
and_return(OpenStruct.new(body:"{\"first_name\":\"John\", \"id\":1234}", headers:{}, status:404))
|
262
|
+
object = ExampleClient.new(first_name:"John", should_disappear:true)
|
263
|
+
begin
|
264
|
+
object.create
|
265
|
+
rescue ActiveRestClient::HTTPNotFoundClientException => e
|
266
|
+
e
|
267
|
+
end
|
268
|
+
expect(e).to be_instance_of(ActiveRestClient::HTTPNotFoundClientException)
|
269
|
+
expect(e.status).to eq(404)
|
270
|
+
expect(e.result.first_name).to eq("John")
|
271
|
+
end
|
272
|
+
|
273
|
+
it "should raise a client exceptions for 4xx errors" do
|
274
|
+
ActiveRestClient::Connection.
|
275
|
+
any_instance.
|
276
|
+
should_receive(:post).
|
277
|
+
with("/create", "first_name=John&should_disappear=true", an_instance_of(Hash)).
|
278
|
+
and_return(OpenStruct.new(body:"{\"first_name\":\"John\", \"id\":1234}", headers:{}, status:409))
|
279
|
+
object = ExampleClient.new(first_name:"John", should_disappear:true)
|
280
|
+
begin
|
281
|
+
object.create
|
282
|
+
rescue ActiveRestClient::HTTPClientException => e
|
283
|
+
e
|
284
|
+
end
|
285
|
+
expect(e).to be_instance_of(ActiveRestClient::HTTPClientException)
|
286
|
+
expect(e.status).to eq(409)
|
287
|
+
expect(e.result.first_name).to eq("John")
|
288
|
+
end
|
289
|
+
|
290
|
+
it "should raise a server exception for 5xx errors" do
|
291
|
+
ActiveRestClient::Connection.
|
292
|
+
any_instance.
|
293
|
+
should_receive(:post).
|
294
|
+
with("/create", "first_name=John&should_disappear=true", an_instance_of(Hash)).
|
295
|
+
and_return(OpenStruct.new(body:"{\"first_name\":\"John\", \"id\":1234}", headers:{}, status:500))
|
296
|
+
object = ExampleClient.new(first_name:"John", should_disappear:true)
|
297
|
+
begin
|
298
|
+
object.create
|
299
|
+
rescue ActiveRestClient::HTTPServerException => e
|
300
|
+
e
|
301
|
+
end
|
302
|
+
expect(e).to be_instance_of(ActiveRestClient::HTTPServerException)
|
303
|
+
expect(e.status).to eq(500)
|
304
|
+
expect(e.result.first_name).to eq("John")
|
305
|
+
end
|
306
|
+
|
307
|
+
it "should raise a parse exception for invalid JSON returns" do
|
308
|
+
error_content = "<h1>500 Server Error</h1>"
|
309
|
+
ActiveRestClient::Connection.
|
310
|
+
any_instance.
|
311
|
+
should_receive(:post).
|
312
|
+
with("/create", "first_name=John&should_disappear=true", an_instance_of(Hash)).
|
313
|
+
and_return(OpenStruct.new(body:error_content, headers:{}, status:500))
|
314
|
+
object = ExampleClient.new(first_name:"John", should_disappear:true)
|
315
|
+
begin
|
316
|
+
object.create
|
317
|
+
rescue ActiveRestClient::ResponseParseException => e
|
318
|
+
e
|
319
|
+
end
|
320
|
+
expect(e).to be_instance_of(ActiveRestClient::ResponseParseException)
|
321
|
+
expect(e.status).to eq(500)
|
322
|
+
expect(e.body).to eq(error_content)
|
323
|
+
end
|
324
|
+
|
325
|
+
it "should raise an exception if you try to pass in an unsupport method" do
|
326
|
+
method = {:method => :wiggle, url:"/"}
|
327
|
+
class RequestFakeObject
|
328
|
+
def base_url
|
329
|
+
"http://www.example.com/"
|
330
|
+
end
|
331
|
+
|
332
|
+
def name ; end
|
333
|
+
def _filter_request(*args) ; end
|
334
|
+
def verbose ; false ; end
|
335
|
+
end
|
336
|
+
fake_object = RequestFakeObject.new
|
337
|
+
request = ActiveRestClient::Request.new(method, fake_object, {})
|
338
|
+
expect{request.call}.to raise_error(ActiveRestClient::InvalidRequestException)
|
339
|
+
end
|
340
|
+
|
341
|
+
it "should send all class mapped methods through _filter_request" do
|
342
|
+
ActiveRestClient::Connection.any_instance.should_receive(:get).with("/", an_instance_of(Hash)).and_return(OpenStruct.new(body:"{\"first_name\":\"Johnny\", \"expenses\":[{\"amount\":1}, {\"amount\":2}]}", status:200, headers:{}))
|
343
|
+
ExampleClient.should_receive(:_filter_request).with(any_args)
|
344
|
+
ExampleClient.all
|
345
|
+
end
|
346
|
+
|
347
|
+
it "should send all instance mapped methods through _filter_request" do
|
348
|
+
ActiveRestClient::Connection.any_instance.should_receive(:get).with("/", an_instance_of(Hash)).and_return(OpenStruct.new(body:"{\"first_name\":\"Johnny\", \"expenses\":[{\"amount\":1}, {\"amount\":2}]}", status:200, headers:{}))
|
349
|
+
ExampleClient.should_receive(:_filter_request).with(any_args)
|
350
|
+
e = ExampleClient.new
|
351
|
+
e.all
|
352
|
+
end
|
353
|
+
|
354
|
+
context "Direct URL requests" do
|
355
|
+
class SameServerExampleClient < ActiveRestClient::Base
|
356
|
+
URL = "http://www.example.com/some/url"
|
357
|
+
base_url "http://www.example.com/v1"
|
358
|
+
get :same_server, "/does-not-matter", url:URL
|
359
|
+
end
|
360
|
+
|
361
|
+
class OtherServerExampleClient < ActiveRestClient::Base
|
362
|
+
URL = "http://other.example.com/some/url"
|
363
|
+
base_url "http://www.example.com/v1"
|
364
|
+
get :other_server, "/does-not-matter", url:URL
|
365
|
+
end
|
366
|
+
|
367
|
+
it "should allow requests directly to URLs" do
|
368
|
+
ActiveRestClient::ConnectionManager.reset!
|
369
|
+
ActiveRestClient::Connection.
|
370
|
+
any_instance.
|
371
|
+
should_receive(:get).
|
372
|
+
with("/some/url", an_instance_of(Hash)).
|
373
|
+
and_return(OpenStruct.new(body:"{\"first_name\":\"John\", \"id\":1234}", headers:{}, status:200))
|
374
|
+
SameServerExampleClient.same_server
|
375
|
+
end
|
376
|
+
|
377
|
+
it "should allow requests directly to URLs even if to different URLs" do
|
378
|
+
ActiveRestClient::ConnectionManager.reset!
|
379
|
+
connection = double("Connection")
|
380
|
+
connection.
|
381
|
+
should_receive(:get).
|
382
|
+
with("/some/url", an_instance_of(Hash)).
|
383
|
+
and_return(OpenStruct.new(body:"", headers:{}, status:304))
|
384
|
+
connection.
|
385
|
+
stub(:base_url).
|
386
|
+
and_return("http://other.example.com")
|
387
|
+
ActiveRestClient::ConnectionManager.should_receive(:find_connection_for_url).with(OtherServerExampleClient::URL).and_return(connection)
|
388
|
+
OtherServerExampleClient.other_server
|
389
|
+
end
|
390
|
+
|
391
|
+
it "should allow requests to partial URLs using the current base_url" do
|
392
|
+
ActiveRestClient::ConnectionManager.reset!
|
393
|
+
connection = double("Connection").as_null_object
|
394
|
+
ActiveRestClient::ConnectionManager.should_receive(:get_connection).with("http://www.example.com").and_return(connection)
|
395
|
+
connection.
|
396
|
+
should_receive(:get).
|
397
|
+
with("/people", an_instance_of(Hash)).
|
398
|
+
and_return(OpenStruct.new(body:"{\"first_name\":\"John\", \"id\":1234}", headers:{}, status:200))
|
399
|
+
@obj = SameServerExampleClient._request('/people')
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
# HAL is Hypermedia Application Language
|
404
|
+
context "HAL" do
|
405
|
+
let(:hal) { ExampleClient.hal }
|
406
|
+
|
407
|
+
it "should request a HAL response or plain JSON" do
|
408
|
+
ActiveRestClient::Connection.any_instance.should_receive(:get).with("/headers", hash_including("Accept" => "application/hal+json, application/json;q=0.5")).and_return(OpenStruct.new(body:'{"result":true}', headers:{}))
|
409
|
+
ExampleClient.headers
|
410
|
+
end
|
411
|
+
|
412
|
+
it "should recognise a HAL response" do
|
413
|
+
method = {:method => :get, url:"/"}
|
414
|
+
class RequestFakeObject
|
415
|
+
def base_url
|
416
|
+
"http://www.example.com/"
|
417
|
+
end
|
418
|
+
|
419
|
+
def name ; end
|
420
|
+
def _filter_request(*args) ; end
|
421
|
+
end
|
422
|
+
fake_object = RequestFakeObject.new
|
423
|
+
request = ActiveRestClient::Request.new(method, fake_object, {})
|
424
|
+
request.instance_variable_set(:@response, OpenStruct.new(headers:{"Content-Type" => "application/hal+json"}))
|
425
|
+
expect(request.hal_response?).to be_true
|
426
|
+
request.instance_variable_set(:@response, OpenStruct.new(headers:{"Content-Type" => "application/json"}))
|
427
|
+
expect(request.hal_response?).to be_true
|
428
|
+
request.instance_variable_set(:@response, OpenStruct.new(headers:{"Content-Type" => "text/plain"}))
|
429
|
+
expect(request.hal_response?).to be_false
|
430
|
+
request.instance_variable_set(:@response, OpenStruct.new(headers:{"Content-Type" => ["text/plain", "application/hal+json"]}))
|
431
|
+
expect(request.hal_response?).to be_true
|
432
|
+
request.instance_variable_set(:@response, OpenStruct.new(headers:{"Content-Type" => ["text/plain", "application/json"]}))
|
433
|
+
expect(request.hal_response?).to be_true
|
434
|
+
request.instance_variable_set(:@response, OpenStruct.new(headers:{"Content-Type" => ["text/plain"]}))
|
435
|
+
expect(request.hal_response?).to be_false
|
436
|
+
end
|
437
|
+
|
438
|
+
it "should map _links in to the normal attributes" do
|
439
|
+
expect(hal.child).to be_an_instance_of(ExampleClient)
|
440
|
+
expect(hal.cars.size).to eq(3)
|
441
|
+
end
|
442
|
+
|
443
|
+
it "should be able to use other attributes of _links using _hal_attributes method with a key" do
|
444
|
+
expect(hal.child).to be_an_instance_of(ExampleClient)
|
445
|
+
expect(hal.cars[2]._hal_attributes("name")).to eq('car_not_embed')
|
446
|
+
end
|
447
|
+
|
448
|
+
it "should use _embedded responses instead of lazy loading if possible" do
|
449
|
+
expect(hal.child.name).to eq("Billy")
|
450
|
+
expect(hal.cars.first.make).to eq("Bugatti")
|
451
|
+
end
|
452
|
+
|
453
|
+
it "should instantiate other classes defined using has_many when using _embedded responses" do
|
454
|
+
expect(hal.other).to be_an(ExampleOtherClient)
|
455
|
+
end
|
456
|
+
|
457
|
+
it "should convert invalid _embedded responses in to lazy loading on error" do
|
458
|
+
expect(hal.invalid.first).to be_an_instance_of(ActiveRestClient::LazyAssociationLoader)
|
459
|
+
end
|
460
|
+
|
461
|
+
it "should lazy load _links attributes if not embedded" do
|
462
|
+
expect(hal.lazy).to be_an_instance_of(ActiveRestClient::LazyAssociationLoader)
|
463
|
+
expect(hal.lazy.instance_variable_get(:@url)).to eq("/lazy/load")
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
467
|
+
it "replaces the body completely in a filter" do
|
468
|
+
ActiveRestClient::Connection.any_instance.should_receive(:post).with("/save", "{\":id\":1234,\":name\":\"john\"}", an_instance_of(Hash)).and_return(OpenStruct.new(body:"{}", headers:{}))
|
469
|
+
FilteredBodyExampleClient.save id:1234, name:'john'
|
470
|
+
end
|
471
|
+
end
|