active_rest_client 0.9.58
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.
- 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
|