restfully 0.3.2 → 0.4.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.
- data/CHANGELOG +6 -0
- data/README.rdoc +82 -92
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/bin/restfully +10 -46
- data/examples/grid5000.rb +5 -5
- data/lib/restfully.rb +3 -2
- data/lib/restfully/collection.rb +64 -139
- data/lib/restfully/extensions.rb +0 -17
- data/lib/restfully/http/adapters/abstract_adapter.rb +1 -1
- data/lib/restfully/http/adapters/rest_client_adapter.rb +25 -3
- data/lib/restfully/http/request.rb +20 -3
- data/lib/restfully/http/response.rb +21 -3
- data/lib/restfully/link.rb +4 -3
- data/lib/restfully/resource.rb +144 -74
- data/lib/restfully/session.rb +36 -22
- data/restfully.gemspec +9 -4
- data/spec/collection_spec.rb +24 -25
- data/spec/http/request_spec.rb +6 -2
- data/spec/http/response_spec.rb +4 -0
- data/spec/http/rest_client_adapter_spec.rb +3 -2
- data/spec/link_spec.rb +7 -4
- data/spec/resource_spec.rb +31 -56
- data/spec/session_spec.rb +77 -41
- metadata +13 -2
data/lib/restfully/session.rb
CHANGED
@@ -10,7 +10,7 @@ module Restfully
|
|
10
10
|
end
|
11
11
|
class Session
|
12
12
|
include Parsing, HTTP::Headers
|
13
|
-
attr_reader :base_uri, :
|
13
|
+
attr_reader :base_uri, :logger, :connection, :root, :default_headers
|
14
14
|
|
15
15
|
# TODO: use CacheableResource
|
16
16
|
def initialize(options = {})
|
@@ -18,38 +18,52 @@ module Restfully
|
|
18
18
|
if (config_filename = options.delete(:configuration_file)) && File.exists?(File.expand_path(config_filename))
|
19
19
|
config = YAML.load_file(File.expand_path(config_filename)).symbolize_keys
|
20
20
|
options.merge!(config)
|
21
|
-
end
|
22
|
-
@base_uri = options.delete(:base_uri) || "http://localhost:8888"
|
23
|
-
|
21
|
+
end
|
22
|
+
@base_uri = URI.parse(options.delete(:base_uri) || "http://localhost:8888") rescue nil
|
23
|
+
raise ArgumentError.new("#{@base_uri} is not a valid URI") if @base_uri.nil? || @base_uri.scheme !~ /^http/i
|
24
24
|
@logger = options.delete(:logger) || NullLogger.new
|
25
|
+
@logger.level = options.delete(:verbose) ? Logger::DEBUG : @logger.level
|
25
26
|
user_default_headers = sanitize_http_headers(options.delete(:default_headers) || {})
|
26
27
|
@default_headers = {'User-Agent' => "Restfully/#{Restfully::VERSION}", 'Accept' => 'application/json'}.merge(user_default_headers)
|
27
|
-
@connection
|
28
|
-
@root
|
28
|
+
@connection = Restfully.adapter.new(base_uri.to_s, options.merge(:logger => logger))
|
29
|
+
@root = Resource.new(@base_uri, self)
|
29
30
|
yield @root.load, self if block_given?
|
30
31
|
end
|
31
32
|
|
32
|
-
#
|
33
|
+
# returns an HTTP::Response object or raise a Restfully::HTTP::Error
|
34
|
+
def head(path, options = {})
|
35
|
+
options = options.symbolize_keys
|
36
|
+
transmit :head, HTTP::Request.new(uri_for(path), :headers => options.delete(:headers), :query => options.delete(:query))
|
37
|
+
end
|
38
|
+
|
39
|
+
# returns an HTTP::Response object or raise a Restfully::HTTP::Error
|
33
40
|
def get(path, options = {})
|
34
|
-
path = path.to_s
|
35
41
|
options = options.symbolize_keys
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
response = deal_with_eventual_errors(response, request)
|
42
|
+
transmit :get, HTTP::Request.new(uri_for(path), :headers => options.delete(:headers), :query => options.delete(:query))
|
43
|
+
end
|
44
|
+
|
45
|
+
# returns an HTTP::Response object or raise a Restfully::HTTP::Error
|
46
|
+
def post(path, body, options = {})
|
47
|
+
options = options.symbolize_keys
|
48
|
+
uri = uri_for(path)
|
49
|
+
transmit :post, HTTP::Request.new(uri_for(path), :body => body, :headers => options.delete(:headers), :query => options.delete(:query))
|
50
|
+
end
|
51
|
+
|
52
|
+
# builds the complete URI, based on the given path and the session's base_uri
|
53
|
+
def uri_for(path)
|
54
|
+
URI.join(base_uri.to_s, path.to_s)
|
50
55
|
end
|
51
56
|
|
52
57
|
protected
|
58
|
+
def transmit(method, request)
|
59
|
+
request.add_headers(default_headers) unless default_headers.empty?
|
60
|
+
logger.info "#{method.to_s.upcase} #{request.uri}" +
|
61
|
+
"\nHeaders: #{request.headers.inspect}" +
|
62
|
+
"#{request.body ? "\nBody: #{request.body.length} bytes" : ""}"
|
63
|
+
response = connection.send(method.to_sym, request)
|
64
|
+
response = deal_with_eventual_errors(response, request)
|
65
|
+
end
|
66
|
+
|
53
67
|
def deal_with_eventual_errors(response, request)
|
54
68
|
case response.status
|
55
69
|
when 400..499
|
data/restfully.gemspec
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{restfully}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.4.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Cyril Rohr"]
|
12
|
-
s.date = %q{2009-11-
|
12
|
+
s.date = %q{2009-11-16}
|
13
13
|
s.default_executable = %q{restfully}
|
14
14
|
s.description = %q{Experimental code for auto-generation of wrappers on top of RESTful APIs that follow HATEOAS principles and provide OPTIONS methods and/or Allow headers.}
|
15
15
|
s.email = %q{cyril.rohr@gmail.com}
|
@@ -21,6 +21,7 @@ Gem::Specification.new do |s|
|
|
21
21
|
s.files = [
|
22
22
|
".document",
|
23
23
|
".gitignore",
|
24
|
+
"CHANGELOG",
|
24
25
|
"LICENSE",
|
25
26
|
"README.rdoc",
|
26
27
|
"Rakefile",
|
@@ -89,10 +90,14 @@ Gem::Specification.new do |s|
|
|
89
90
|
|
90
91
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
91
92
|
s.add_runtime_dependency(%q<rest-client>, [">= 1.0"])
|
93
|
+
s.add_runtime_dependency(%q<backports>, [">= 0"])
|
92
94
|
else
|
93
95
|
s.add_dependency(%q<rest-client>, [">= 1.0"])
|
96
|
+
s.add_dependency(%q<backports>, [">= 0"])
|
94
97
|
end
|
95
98
|
else
|
96
99
|
s.add_dependency(%q<rest-client>, [">= 1.0"])
|
100
|
+
s.add_dependency(%q<backports>, [">= 0"])
|
97
101
|
end
|
98
102
|
end
|
103
|
+
|
data/spec/collection_spec.rb
CHANGED
@@ -4,53 +4,54 @@ include Restfully
|
|
4
4
|
describe Collection do
|
5
5
|
describe "general behaviour" do
|
6
6
|
before do
|
7
|
-
@
|
7
|
+
@uri = URI.parse('http://api.local/x/y/z')
|
8
|
+
@collection = Collection.new(@uri, session=mock('session')).load(:body => JSON.parse(fixture("grid5000-sites.json")))
|
8
9
|
end
|
9
10
|
it "should be enumerable" do
|
10
11
|
@collection.length.should == 9
|
12
|
+
@collection.size.should == 9
|
11
13
|
@collection.map{|site| site["uid"]}.sort.should == ["bordeaux", "grenoble", "lille", "lyon", "nancy", "orsay", "rennes", "sophia", "toulouse"]
|
12
14
|
end
|
13
15
|
|
14
|
-
it "should have a :total
|
15
|
-
@collection
|
16
|
+
it "should have a :total attribute" do
|
17
|
+
@collection["total"].should == 9
|
16
18
|
end
|
17
19
|
|
18
|
-
it "should have a :offset
|
19
|
-
@collection
|
20
|
+
it "should have a :offset attribute" do
|
21
|
+
@collection["offset"].should == 0
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
23
25
|
describe "loading" do
|
24
26
|
before(:all) do
|
27
|
+
@uri = URI.parse('http://api.local/x/y/z')
|
25
28
|
@raw = fixture("grid5000-sites.json")
|
26
29
|
@response_200 = Restfully::HTTP::Response.new(200, {'Content-Type' => 'application/json;charset=utf-8', 'Content-Length' => @raw.length}, @raw)
|
27
30
|
@logger = Logger.new(STDOUT)
|
28
31
|
end
|
29
32
|
it "should not load if already loaded and no :reload" do
|
30
|
-
collection = Collection.new(
|
31
|
-
|
32
|
-
collection.
|
33
|
-
collection.load(:reload => false).should == collection
|
33
|
+
collection = Collection.new(@uri, mock("session"))
|
34
|
+
options = {:headers => {'key' => 'value'}}
|
35
|
+
collection.should_receive(:executed_requests).and_return({'GET' => {'options' => options, 'body' => {"key", "value"}}})
|
36
|
+
collection.load(options.merge(:reload => false)).should == collection
|
34
37
|
end
|
35
38
|
it "should load when :reload param is true [already loaded]" do
|
36
|
-
collection = Collection.new(
|
37
|
-
collection.should_receive(:loaded?).and_return(true)
|
39
|
+
collection = Collection.new(@uri, session=mock("session", :logger => Logger.new(STDOUT)))
|
38
40
|
session.should_receive(:get).and_return(@response_200)
|
39
41
|
collection.load(:reload => true).should == collection
|
40
42
|
end
|
41
43
|
it "should load when force_reload is true [not loaded]" do
|
42
|
-
collection = Collection.new(
|
43
|
-
collection.should_receive(:loaded?).and_return(false)
|
44
|
+
collection = Collection.new(@uri, session=mock("session", :logger => Logger.new(STDOUT)))
|
44
45
|
session.should_receive(:get).and_return(@response_200)
|
45
46
|
collection.load(:reload => true).should == collection
|
46
47
|
end
|
47
48
|
it "should force reload when query parameters are given" do
|
48
|
-
collection = Collection.new(
|
49
|
+
collection = Collection.new(@uri, session=mock("session", :logger => Logger.new(STDOUT)))
|
49
50
|
session.should_receive(:get).and_return(@response_200)
|
50
51
|
collection.load(:query => {:q1 => 'v1'}).should == collection
|
51
52
|
end
|
52
53
|
it "should not initialize resources lacking a self link" do
|
53
|
-
collection = Collection.new(
|
54
|
+
collection = Collection.new(@uri, session = mock("session", :get => mock("restfully response", :body => {
|
54
55
|
"total" => 1,
|
55
56
|
"offset" => 0,
|
56
57
|
"items" => [
|
@@ -64,10 +65,10 @@ describe Collection do
|
|
64
65
|
}), :logger => @logger))
|
65
66
|
Resource.should_not_receive(:new)
|
66
67
|
collection.load
|
67
|
-
collection.
|
68
|
+
collection.find{|i| i['uid'] == 'rennes'}.should be_nil
|
68
69
|
end
|
69
70
|
it "should initialize resources having a self link" do
|
70
|
-
collection = Collection.new(
|
71
|
+
collection = Collection.new(@uri, session = mock("session", :get => mock("restfully response", :body => {
|
71
72
|
"total" => 1,
|
72
73
|
"offset" => 0,
|
73
74
|
"items" => [
|
@@ -82,17 +83,15 @@ describe Collection do
|
|
82
83
|
}), :logger => @logger))
|
83
84
|
collection.load
|
84
85
|
collection.length.should == 1
|
85
|
-
collection.
|
86
|
+
collection.find{|i| i['uid'] == 'rennes'}.class.should == Restfully::Resource
|
86
87
|
end
|
87
88
|
it "should correctly initialize its resources [integration test]" do
|
88
|
-
collection = Collection.new(
|
89
|
+
collection = Collection.new(@uri, session=mock("session", :logger => Logger.new(STDOUT), :get => @response_200))
|
89
90
|
collection.load
|
90
|
-
collection.should
|
91
|
-
collection.
|
92
|
-
collection.
|
93
|
-
collection.
|
94
|
-
collection.by_uid.keys.should =~ ['rennes', 'lille', 'bordeaux', 'nancy', 'sophia', 'toulouse', 'lyon', 'grenoble', 'orsay']
|
95
|
-
collection.by_uid('rennes', 'bordeaux').length.should == 2
|
91
|
+
collection.uri.should == @uri
|
92
|
+
collection.find{|i| i['uid'] == 'rennes'}["uid"].should == 'rennes'
|
93
|
+
collection.find{|i| i['uid'] == 'rennes'}["type"].should == 'site'
|
94
|
+
collection.map{|s| s['uid']}.should =~ ['rennes', 'lille', 'bordeaux', 'nancy', 'sophia', 'toulouse', 'lyon', 'grenoble', 'orsay']
|
96
95
|
end
|
97
96
|
end
|
98
97
|
|
data/spec/http/request_spec.rb
CHANGED
@@ -4,16 +4,20 @@ describe Restfully::HTTP::Request do
|
|
4
4
|
it "should correctly initialize the attributes" do
|
5
5
|
request = Restfully::HTTP::Request.new(
|
6
6
|
'https://api.grid5000.fr/sid/grid5000?q1=v1&q2=v2',
|
7
|
-
:headers => {'accept' => 'application/json', :cache_control => 'max-age=0'},
|
8
|
-
:query => {'custom_param1' => [3, 4, 5, 6], 'custom_param2' => 'value_custom_param2'}
|
7
|
+
:headers => {'accept' => 'application/json', :cache_control => 'max-age=0', 'Content-Type' => 'application/json'},
|
8
|
+
:query => {'custom_param1' => [3, 4, 5, 6], 'custom_param2' => 'value_custom_param2'},
|
9
|
+
:body => {"key" => "value"}.to_json
|
9
10
|
)
|
10
11
|
request.uri.should be_a URI
|
11
12
|
request.uri.to_s.should == 'https://api.grid5000.fr/sid/grid5000?q1=v1&q2=v2&custom_param1=3,4,5,6&custom_param2=value_custom_param2'
|
12
13
|
request.uri.query.should == "q1=v1&q2=v2&custom_param1=3,4,5,6&custom_param2=value_custom_param2"
|
13
14
|
request.headers.should == {
|
15
|
+
"Content-Type"=>"application/json",
|
14
16
|
'Accept' => 'application/json',
|
15
17
|
'Cache-Control' => 'max-age=0'
|
16
18
|
}
|
19
|
+
request.body.should == {"key" => "value"}
|
20
|
+
request.raw_body.should == "{\"key\":\"value\"}"
|
17
21
|
request.retries.should == 0
|
18
22
|
end
|
19
23
|
|
data/spec/http/response_spec.rb
CHANGED
@@ -12,4 +12,8 @@ describe Restfully::HTTP::Response do
|
|
12
12
|
'property2' => 'value2'
|
13
13
|
}
|
14
14
|
end
|
15
|
+
it "should return the unserialized body" do
|
16
|
+
response = Restfully::HTTP::Response.new(404, {:content_type => 'application/json;charset=utf-8'}, '{"property1": "value1", "property2": "value2"}')
|
17
|
+
response.raw_body.should == "{\"property1\": \"value1\", \"property2\": \"value2\"}"
|
18
|
+
end
|
15
19
|
end
|
@@ -19,7 +19,7 @@ describe Restfully::HTTP::Adapters::RestClientAdapter do
|
|
19
19
|
end
|
20
20
|
it "should raise a not implemented error when trying to use functions not implemented yet" do
|
21
21
|
adapter = Restfully::HTTP::Adapters::RestClientAdapter.new("https://api.grid5000.fr")
|
22
|
-
lambda{adapter.
|
22
|
+
lambda{adapter.delete(mock("restfully request"))}.should raise_error NotImplementedError, "DELETE is not supported by your adapter."
|
23
23
|
end
|
24
24
|
it "should rescue any RestClient::Exception and correctly populate the response" do
|
25
25
|
res = mock(Net::HTTPResponse, :code => 404, :body => '{"message":"whatever"}', :to_hash => {'Content-Type' => 'application/json;charset=utf-8', 'Content-Length' => 22}, :[] => '')
|
@@ -28,6 +28,7 @@ describe Restfully::HTTP::Adapters::RestClientAdapter do
|
|
28
28
|
response = adapter.get(mock("request", :uri => "uri"))
|
29
29
|
response.status.should == 404
|
30
30
|
response.headers.should == {'Content-Type' => 'application/json;charset=utf-8', 'Content-Length' => 22}
|
31
|
-
response.
|
31
|
+
response.raw_body.should == '{"message":"whatever"}'
|
32
|
+
response.body.should == {"message"=>"whatever"}
|
32
33
|
end
|
33
34
|
end
|
data/spec/link_spec.rb
CHANGED
@@ -2,7 +2,9 @@ require File.expand_path(File.dirname(__FILE__)+'/spec_helper')
|
|
2
2
|
|
3
3
|
include Restfully
|
4
4
|
describe Link do
|
5
|
-
|
5
|
+
before do
|
6
|
+
@uri = URI.parse('/x/y/z')
|
7
|
+
end
|
6
8
|
it "should have a rel reader" do
|
7
9
|
link = Link.new
|
8
10
|
link.should_not respond_to(:rel=)
|
@@ -28,7 +30,7 @@ describe Link do
|
|
28
30
|
link.should respond_to(:valid?)
|
29
31
|
end
|
30
32
|
it "should respond to resolved?" do
|
31
|
-
link = Link.new
|
33
|
+
link = Link.new("href" => @uri)
|
32
34
|
link.should respond_to(:resolved?)
|
33
35
|
end
|
34
36
|
it "should respond to resolvable?" do
|
@@ -43,9 +45,10 @@ describe Link do
|
|
43
45
|
link = Link.new
|
44
46
|
link.should_not be_resolved
|
45
47
|
end
|
46
|
-
it "should
|
48
|
+
it "should be valid even if the href is ''" do
|
47
49
|
link = Link.new 'rel' => 'collection', 'title' => 'my collection'
|
48
|
-
link.
|
50
|
+
link.should be_valid
|
51
|
+
link.href.should == URI.parse("")
|
49
52
|
end
|
50
53
|
it "should not be valid if there is no rel" do
|
51
54
|
link = Link.new 'href' => '/', 'title' => 'my collection'
|
data/spec/resource_spec.rb
CHANGED
@@ -7,16 +7,6 @@ describe Resource do
|
|
7
7
|
@logger = Logger.new(STDOUT)
|
8
8
|
end
|
9
9
|
|
10
|
-
it "should have all the methods of a hash" do
|
11
|
-
resource = Resource.new("uri", session=mock('session'))
|
12
|
-
resource.size.should == 0
|
13
|
-
resource['whatever'] = 'thing'
|
14
|
-
resource.size.should == 1
|
15
|
-
resource.should == {'whatever' => 'thing'}
|
16
|
-
resource.should respond_to(:each)
|
17
|
-
resource.should respond_to(:length)
|
18
|
-
end
|
19
|
-
|
20
10
|
describe "accessors" do
|
21
11
|
it "should have a reader on the session" do
|
22
12
|
resource = Resource.new("uri", session=mock("session"))
|
@@ -26,17 +16,7 @@ describe Resource do
|
|
26
16
|
it "should have a reader on the uri" do
|
27
17
|
resource = Resource.new("uri", session=mock("session"))
|
28
18
|
resource.should_not respond_to(:uri=)
|
29
|
-
resource.uri.should == "uri"
|
30
|
-
end
|
31
|
-
it "should have a reader on the raw property" do
|
32
|
-
resource = Resource.new("uri", session=mock("session"))
|
33
|
-
resource.should_not respond_to(:raw=)
|
34
|
-
resource.load('raw' => {:a => :b}).raw.should == {:a => :b}
|
35
|
-
end
|
36
|
-
it "should have a reader on the state property" do
|
37
|
-
resource = Resource.new("uri", session=mock("session"))
|
38
|
-
resource.should_not respond_to(:state=)
|
39
|
-
resource.state.should == :unloaded
|
19
|
+
resource.uri.should == URI.parse("uri")
|
40
20
|
end
|
41
21
|
end
|
42
22
|
|
@@ -85,97 +65,92 @@ describe Resource do
|
|
85
65
|
'model' => 'XYZ1b'
|
86
66
|
}
|
87
67
|
}
|
88
|
-
}
|
89
|
-
@response_200 = Restfully::HTTP::Response.new(200, {'Content-Type' => 'application/json;utf-8', 'Content-Length' => @raw.length}, @raw)
|
68
|
+
}
|
69
|
+
@response_200 = Restfully::HTTP::Response.new(200, {'Content-Type' => 'application/json;utf-8', 'Content-Length' => @raw.length}, @raw.to_json)
|
70
|
+
@uri = URI.parse("http://api.local/x/y/z")
|
90
71
|
end
|
91
72
|
it "should not be loaded in its initial state" do
|
92
|
-
resource = Resource.new(
|
93
|
-
resource.
|
73
|
+
resource = Resource.new(@uri, mock('session'))
|
74
|
+
resource.executed_requests.should == {}
|
94
75
|
end
|
95
76
|
it "should get the raw representation of the resource via the session if it doesn't have it" do
|
96
|
-
resource = Resource.new(uri
|
77
|
+
resource = Resource.new(@uri, session = mock("session", :logger => Logger.new(STDOUT)))
|
97
78
|
resource.stub!(:define_link) # do not define links
|
98
|
-
|
99
|
-
session.should_receive(:get).with(uri, {}).and_return(@response_200)
|
79
|
+
session.should_receive(:get).with(@uri, {}).and_return(@response_200)
|
100
80
|
resource.load
|
101
|
-
resource.should be_loaded
|
102
81
|
end
|
103
82
|
it "should get the raw representation of the resource via the session if there are query parameters" do
|
104
|
-
resource = Resource.new(uri
|
83
|
+
resource = Resource.new(@uri, session = mock("session", :logger => Logger.new(STDOUT)))
|
105
84
|
resource.stub!(:define_link) # do not define links
|
106
|
-
|
107
|
-
resource.raw.should be_nil
|
108
|
-
session.should_receive(:get).with(uri, {:query => {:q1 => 'v1'}}).and_return(@response_200)
|
85
|
+
session.should_receive(:get).with(@uri, {:query => {:q1 => 'v1'}}).and_return(@response_200)
|
109
86
|
resource.load(:query => {:q1 => 'v1'})
|
110
87
|
end
|
111
88
|
it "should get the raw representation of the resource if forced to do so" do
|
112
|
-
resource = Resource.new(uri
|
89
|
+
resource = Resource.new(@uri, session = mock("session", :logger => Logger.new(STDOUT)))
|
113
90
|
resource.stub!(:define_link) # do not define links
|
114
|
-
|
115
|
-
resource.raw.should be_nil
|
116
|
-
session.should_receive(:get).with(uri, {}).and_return(@response_200)
|
91
|
+
session.should_receive(:get).with(@uri, {}).and_return(@response_200)
|
117
92
|
resource.load(:reload => true)
|
118
93
|
end
|
119
94
|
it "should correctly define the functions to access simple values" do
|
120
|
-
resource = Resource.new(
|
95
|
+
resource = Resource.new(@uri, session = mock("session", :get => @response_200, :logger => @logger))
|
121
96
|
resource.stub!(:define_link) # do not define links
|
122
97
|
resource.load
|
123
98
|
resource['whatever'].should == 'whatever'
|
124
|
-
resource.uri.should ==
|
99
|
+
resource.uri.should == @uri
|
125
100
|
resource["uid"].should == 'rennes'
|
126
101
|
resource['an_array'].should be_a(SpecialArray)
|
127
102
|
resource['an_array'].should == [1,2,3]
|
128
103
|
lambda{resource.clusters}.should raise_error(NoMethodError)
|
129
104
|
end
|
130
105
|
|
131
|
-
it "should correctly define a collection
|
132
|
-
resource = Resource.new(
|
106
|
+
it "should correctly define a collection link" do
|
107
|
+
resource = Resource.new(@uri, session = mock("session", :get => mock("restfully response", :body => {
|
133
108
|
'links' => [
|
134
109
|
{'rel' => 'self', 'href' => '/grid5000/sites/rennes'},
|
135
110
|
{'rel' => 'collection', 'href' => '/grid5000/sites/rennes/versions', 'resolvable' => false, 'title' => 'versions'}
|
136
111
|
],
|
137
112
|
'uid' => 'rennes'
|
138
113
|
}), :logger => @logger))
|
139
|
-
Collection.should_receive(:new).with('/grid5000/sites/rennes/versions', session, :title => 'versions'
|
114
|
+
Collection.should_receive(:new).with(@uri.merge('/grid5000/sites/rennes/versions'), session, :title => 'versions').and_return(collection=mock("restfully collection"))
|
140
115
|
resource.load
|
141
|
-
resource.
|
116
|
+
resource.links['versions'].should == collection
|
142
117
|
end
|
143
118
|
it "should NOT update the URI with the self link" do
|
144
|
-
resource = Resource.new(
|
119
|
+
resource = Resource.new(@uri, session = mock("session", :get => mock("restfully response", :body => {
|
145
120
|
'links' => [
|
146
121
|
{'rel' => 'self', 'href' => '/grid5000/sites/rennes'}
|
147
122
|
],
|
148
123
|
'uid' => 'rennes'
|
149
124
|
}), :logger => @logger))
|
150
|
-
resource.uri.should ==
|
125
|
+
resource.uri.should == @uri
|
151
126
|
resource.load
|
152
|
-
resource.uri.should ==
|
127
|
+
resource.uri.should == @uri
|
153
128
|
end
|
154
129
|
it "should correctly define a member association" do
|
155
|
-
resource = Resource.new(
|
130
|
+
resource = Resource.new(@uri, session = mock("session", :get => mock("restfully response", :body => {
|
156
131
|
'links' => [
|
157
132
|
{'rel' => 'member', 'href' => '/grid5000/sites/rennes/versions/123', 'title' => 'version'}
|
158
133
|
],
|
159
134
|
'uid' => 'rennes'
|
160
135
|
}), :logger => @logger))
|
161
|
-
Resource.should_receive(:new).with('/grid5000/sites/rennes/versions/123', session, :title => 'version'
|
136
|
+
Resource.should_receive(:new).with(@uri.merge('/grid5000/sites/rennes/versions/123'), session, :title => 'version').and_return(member=mock("restfully resource"))
|
162
137
|
resource.load
|
163
|
-
resource.
|
138
|
+
resource.links['version'].should == member
|
164
139
|
end
|
165
140
|
it "should correctly define a parent association" do
|
166
|
-
resource = Resource.new(
|
141
|
+
resource = Resource.new(@uri, session = mock("session", :get => mock("restfully response", :body => {
|
167
142
|
'links' => [
|
168
143
|
{'rel' => 'self', 'href' => '/grid5000/sites/rennes'},
|
169
144
|
{'rel' => 'parent', 'href' => '/grid5000'}
|
170
145
|
],
|
171
146
|
'uid' => 'rennes'
|
172
147
|
}), :logger => @logger))
|
173
|
-
Resource.should_receive(:new).with('/grid5000', session).and_return(parent=mock("restfully resource"))
|
148
|
+
Resource.should_receive(:new).with(@uri.merge('/grid5000'), session).and_return(parent=mock("restfully resource"))
|
174
149
|
resource.load
|
175
|
-
resource.
|
150
|
+
resource.links['parent'].should == parent
|
176
151
|
end
|
177
152
|
it "should ignore bad links" do
|
178
|
-
resource = Resource.new(
|
153
|
+
resource = Resource.new(@uri, session = mock("session", :get => mock("restfully response", :body => {
|
179
154
|
'links' => [
|
180
155
|
{'rel' => 'self', 'href' => '/grid5000/sites/rennes'},
|
181
156
|
{'rel' => 'invalid_rel', 'href' => '/whatever'},
|
@@ -184,15 +159,15 @@ describe Resource do
|
|
184
159
|
'uid' => 'rennes'
|
185
160
|
}), :logger => @logger))
|
186
161
|
resource.load
|
187
|
-
resource.
|
162
|
+
resource.links.should be_empty
|
188
163
|
end
|
189
164
|
|
190
165
|
it "should correctly define the functions to access links [integration test]" do
|
191
|
-
resource = Resource.new(
|
166
|
+
resource = Resource.new(@uri, session = mock("session", :get => @response_200, :logger => @logger))
|
192
167
|
@logger.should_receive(:warn).with(/collection \/has\/no\/title has no title/)
|
193
168
|
@logger.should_receive(:warn).with(/invalid_rel is not a valid link relationship/)
|
194
169
|
resource.load
|
195
|
-
resource.
|
170
|
+
resource.links.keys.should =~ ['versions', 'clusters', 'environments', 'status', 'parent', 'version']
|
196
171
|
end
|
197
172
|
end
|
198
173
|
end
|