resto 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/blankslate.rb +110 -0
- data/lib/resto.rb +264 -0
- data/lib/resto/attributes.rb +56 -0
- data/lib/resto/extra/copy.rb +34 -0
- data/lib/resto/extra/delegation.rb +26 -0
- data/lib/resto/extra/hash_args.rb +56 -0
- data/lib/resto/format.rb +20 -0
- data/lib/resto/format/default.rb +11 -0
- data/lib/resto/format/json.rb +30 -0
- data/lib/resto/format/plain.rb +14 -0
- data/lib/resto/format/xml.rb +66 -0
- data/lib/resto/property.rb +50 -0
- data/lib/resto/property/handler.rb +57 -0
- data/lib/resto/property/integer.rb +29 -0
- data/lib/resto/property/string.rb +19 -0
- data/lib/resto/property/time.rb +43 -0
- data/lib/resto/request/base.rb +88 -0
- data/lib/resto/request/factory.rb +66 -0
- data/lib/resto/request/header.rb +58 -0
- data/lib/resto/request/option.rb +126 -0
- data/lib/resto/request/uri.rb +50 -0
- data/lib/resto/response/base.rb +85 -0
- data/lib/resto/translator/request_factory.rb +44 -0
- data/lib/resto/translator/response_factory.rb +28 -0
- data/lib/resto/validate.rb +37 -0
- data/lib/resto/validate/inclusion.rb +39 -0
- data/lib/resto/validate/length.rb +36 -0
- data/lib/resto/validate/presence.rb +24 -0
- data/lib/resto/version.rb +5 -0
- data/resto.gemspec +43 -0
- data/spec/resto/extra/copy_spec.rb +58 -0
- data/spec/resto/extra/hash_args_spec.rb +71 -0
- data/spec/resto/format/default_spec.rb +24 -0
- data/spec/resto/format/json_spec.rb +29 -0
- data/spec/resto/format/plain_spec.rb +21 -0
- data/spec/resto/format/xml_spec.rb +105 -0
- data/spec/resto/property/handler_spec.rb +57 -0
- data/spec/resto/property/integer_spec.rb +67 -0
- data/spec/resto/property/time_spec.rb +124 -0
- data/spec/resto/property_spec.rb +60 -0
- data/spec/resto/request/base_spec.rb +253 -0
- data/spec/resto/request/factory_spec.rb +114 -0
- data/spec/resto/translator/response_factory_spec.rb +93 -0
- data/spec/resto/validate/presence_spec.rb +102 -0
- data/spec/resto_spec.rb +531 -0
- data/spec/spec_helper.rb +119 -0
- metadata +48 -3
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Resto
|
4
|
+
module Validate
|
5
|
+
|
6
|
+
autoload :Inclusion, 'resto/validate/inclusion'
|
7
|
+
autoload :Length, 'resto/validate/length'
|
8
|
+
autoload :Presence, 'resto/validate/presence'
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@if = lambda { |resource| true }
|
12
|
+
@unless = lambda { |resource| false }
|
13
|
+
end
|
14
|
+
|
15
|
+
def validate?(resource)
|
16
|
+
(@if.call(resource) && !@unless.call(resource))
|
17
|
+
end
|
18
|
+
|
19
|
+
def message(error_message)
|
20
|
+
tap { @message = error_message }
|
21
|
+
end
|
22
|
+
|
23
|
+
def if(&block)
|
24
|
+
tap { @if = block }
|
25
|
+
end
|
26
|
+
|
27
|
+
def unless(&block)
|
28
|
+
tap { @unless = block }
|
29
|
+
end
|
30
|
+
|
31
|
+
# .on - Specifies when this validation is active (default is :save, other
|
32
|
+
# options :create, :update).
|
33
|
+
# def on(args)
|
34
|
+
# tap { }
|
35
|
+
# end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Resto
|
4
|
+
module Validate
|
5
|
+
class Inclusion
|
6
|
+
include Validate
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@allow_nil = false
|
10
|
+
@allow_blank = false
|
11
|
+
end
|
12
|
+
|
13
|
+
def in(range)
|
14
|
+
tap { @range = range }
|
15
|
+
end
|
16
|
+
|
17
|
+
def allow_nil
|
18
|
+
tap { @allow_nil = true }
|
19
|
+
end
|
20
|
+
|
21
|
+
def allow_blank
|
22
|
+
tap { @allow_blank = true }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
#
|
28
|
+
# .in - An enumerable object of available items. %w( m f ), 0..99, %w( jpg gif png )
|
29
|
+
# .message - Specifies a custom error message (default is: “is not included in the list”).
|
30
|
+
# .allow_nil - If set to true, skips this validation if the attribute is nil (default is false).
|
31
|
+
# .allow_blank - If set to true, skips this validation if the attribute is blank (default is false).
|
32
|
+
# .if - Specifies a method, proc or string to call to determine if the validation should occur
|
33
|
+
# (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The method,
|
34
|
+
# proc or string should return or evaluate to a true or false value.
|
35
|
+
# .unless - Specifies a method, proc or string to call to determine if the validation should not occur
|
36
|
+
# (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }).
|
37
|
+
# The method, proc or string should return or evaluate to a true or false value.
|
38
|
+
|
39
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Resto
|
4
|
+
module Validate
|
5
|
+
class Length
|
6
|
+
include Validate
|
7
|
+
|
8
|
+
def is(number)
|
9
|
+
tap { @number = number }
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
# .is - The exact size of the attribute.
|
16
|
+
# .within - A range specifying the minimum and maximum size of the attribute.
|
17
|
+
# .allow_nil - Attribute may be nil; skip validation.
|
18
|
+
# .allow_blank - Attribute may be blank; skip validation.
|
19
|
+
# .if - Specifies a method, proc or string to call to determine if the
|
20
|
+
# validation should occur (e.g. :if => :allow_validation, or :if =>
|
21
|
+
# Proc.new { |user| user.signup_step > 2 }). The method, proc or string should
|
22
|
+
# return or evaluate to a true or false value.
|
23
|
+
# .unless - oposite of .if
|
24
|
+
#
|
25
|
+
# messages
|
26
|
+
# :too_long - The error message if the attribute goes over the maximum
|
27
|
+
# (default is: “is too long (maximum is %count characters)”).
|
28
|
+
# :too_short - The error message if the attribute goes under the minimum
|
29
|
+
# (default is: “is too short (min is %count characters)”).
|
30
|
+
# :wrong_length - The error message if using the :is method and the attribute
|
31
|
+
# is the wrong size (default is: “is the wrong length
|
32
|
+
# (should be %count characters)”).
|
33
|
+
# :message - The error message to use for a :minimum, :maximum, or
|
34
|
+
# :is violation. An alias of the appropriate too_long/too_short/wrong_length
|
35
|
+
# message.
|
36
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Resto
|
4
|
+
module Validate
|
5
|
+
class Presence
|
6
|
+
include Validate
|
7
|
+
|
8
|
+
def attribute_value(resource, attribute_method)
|
9
|
+
|
10
|
+
error_key = (attribute_method.to_s + "_presence").to_sym
|
11
|
+
value_before_cast = resource.send("#{attribute_method}_without_cast")
|
12
|
+
|
13
|
+
error =
|
14
|
+
if (validate?(resource) && value_before_cast.to_s.strip.empty?)
|
15
|
+
":#{attribute_method} #{@message || "can’t be blank"}"
|
16
|
+
else
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
|
20
|
+
resource.add_error(error_key, error)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/resto.gemspec
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
|
4
|
+
require File.expand_path("../lib/resto/version", __FILE__)
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "resto"
|
8
|
+
s.version = Resto::VERSION
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.authors = ["Anders Törnqvist"]
|
11
|
+
s.email = ["anders@elabs.se"]
|
12
|
+
s.homepage = "http://rubygems.org/gems/resto"
|
13
|
+
s.summary = "Restful Web Service"
|
14
|
+
s.description = "Restful Web Service"
|
15
|
+
|
16
|
+
s.required_ruby_version = ::Gem::Requirement.new(">= 1.8.7")
|
17
|
+
s.required_rubygems_version = ">= 1.3.6"
|
18
|
+
s.rubyforge_project = "resto"
|
19
|
+
|
20
|
+
s.add_runtime_dependency "yajl-ruby", "0.8.2"
|
21
|
+
s.add_runtime_dependency "nokogiri", ">=1.4.4"
|
22
|
+
# s.add_dependency "activesupport", "3.0.0" ???
|
23
|
+
s.add_development_dependency "bundler", ">= 1.0.11"
|
24
|
+
s.add_development_dependency "rspec", ">= 2.5.0"
|
25
|
+
s.add_development_dependency "fuubar", ">= 0.0.4"
|
26
|
+
s.add_development_dependency "webmock", ">= 1.6.2"
|
27
|
+
s.add_development_dependency "code-cleaner", ">= 0.8.2"
|
28
|
+
s.add_development_dependency "reek"
|
29
|
+
s.add_development_dependency "metrical"
|
30
|
+
s.add_development_dependency "simplecov"
|
31
|
+
s.add_development_dependency "ephemeral_response"
|
32
|
+
|
33
|
+
# CLI testing
|
34
|
+
# http://github.com/radar/guides/blob/master/gem-development.md
|
35
|
+
# s.add_dependency "thor"
|
36
|
+
# s.add_development_dependency "cucumber"
|
37
|
+
# s.add_development_dependency "aruba"
|
38
|
+
|
39
|
+
s.files = Dir.glob("{lib,spec}/**/*") + %w(resto.gemspec)
|
40
|
+
# s.files = `git ls-files`.split("\n")
|
41
|
+
#s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
42
|
+
s.require_path = 'lib'
|
43
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'resto/extra/copy'
|
5
|
+
describe Resto::Extra::Copy do
|
6
|
+
describe ".request_base" do
|
7
|
+
before do
|
8
|
+
@request_base = Resto::Request::Base.new.port(40)
|
9
|
+
.url('http://www.aftonbladet.se:92/customers')
|
10
|
+
.query('q=adam')
|
11
|
+
.path('contacts')
|
12
|
+
|
13
|
+
@new_request_base = Resto::Extra::Copy.request_base(@request_base)
|
14
|
+
.url('http://new.se:99/other')
|
15
|
+
.query('q=not-same')
|
16
|
+
.path('other-contacts/')
|
17
|
+
.headers({ "accept"=> "other", "user-agent"=> "Ruby" })
|
18
|
+
.append_path(2)
|
19
|
+
end
|
20
|
+
|
21
|
+
it { @new_request_base.object_id.should_not == @request_base.object_id }
|
22
|
+
it { @request_base.read_port.should == 40 }
|
23
|
+
it { @request_base.composed_path.should == '/contacts?q=adam' }
|
24
|
+
|
25
|
+
it do
|
26
|
+
@request_base.composed_headers.should == { "accept"=> "*/*",
|
27
|
+
"user-agent"=> "Ruby" }
|
28
|
+
end
|
29
|
+
|
30
|
+
it do
|
31
|
+
@request_base.composed_headers.object_id.should_not ==
|
32
|
+
@new_request_base.composed_headers.object_id
|
33
|
+
end
|
34
|
+
|
35
|
+
it { @new_request_base.read_port.should == 40 }
|
36
|
+
|
37
|
+
it do
|
38
|
+
@new_request_base.composed_headers.should == { "accept"=> "other",
|
39
|
+
"user-agent"=> "Ruby" }
|
40
|
+
end
|
41
|
+
|
42
|
+
it do
|
43
|
+
@new_request_base.composed_path.should == "/other-contacts/2?q=not-same"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe ".response_base" do
|
48
|
+
before do
|
49
|
+
@response_base = Resto::Response::Base.new.format(:json)
|
50
|
+
@new_response_base = Resto::Extra::Copy.response_base(@response_base)
|
51
|
+
.http_response('response')
|
52
|
+
end
|
53
|
+
|
54
|
+
it { @response_base.instance_eval { @response }.should == nil }
|
55
|
+
it { @new_response_base.object_id.should_not == @response_base.object_id }
|
56
|
+
it { @new_response_base.instance_eval { @response }.should == 'response' }
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'resto/extra/hash_args'
|
5
|
+
|
6
|
+
describe Resto::Extra::HashArgs do
|
7
|
+
|
8
|
+
class_context(%Q{
|
9
|
+
class BasicAuthication < Resto::Extra::HashArgs
|
10
|
+
key :username
|
11
|
+
key :password
|
12
|
+
end}) do
|
13
|
+
|
14
|
+
it "returns the value from the block when no value is found by key" do
|
15
|
+
BasicAuthication.new(nil).fetch(:username) { 'anders' }.should == 'anders'
|
16
|
+
end
|
17
|
+
|
18
|
+
it "returns the value found by the key" do
|
19
|
+
BasicAuthication.new({'username' => 'anders', :password => 'secret'})
|
20
|
+
.fetch(:password) { 'other' }.should == 'secret'
|
21
|
+
end
|
22
|
+
|
23
|
+
it "the key is translated to its symbol" do
|
24
|
+
BasicAuthication.new({'username' => 'anders', :password => 'secret'})
|
25
|
+
.fetch(:username) { 'other' }.should == 'anders'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class_context(%Q{
|
30
|
+
class FormatExt < Resto::Extra::HashArgs
|
31
|
+
key :extension
|
32
|
+
end}) do
|
33
|
+
|
34
|
+
it "returns the value from the block" do
|
35
|
+
FormatExt.new({}).fetch(:extension) { 'block' }.should == 'block'
|
36
|
+
end
|
37
|
+
|
38
|
+
if RUBY_VERSION < '1.9'
|
39
|
+
|
40
|
+
it "raises IndexError when no value and no block" do
|
41
|
+
expect { FormatExt.new({}).fetch(:extension) }
|
42
|
+
.to raise_error(IndexError, 'key not found')
|
43
|
+
end
|
44
|
+
|
45
|
+
else
|
46
|
+
|
47
|
+
it "raises KeyError when no value and no block" do
|
48
|
+
lambda { FormatExt.new({}).fetch(:extension) }
|
49
|
+
.should raise_error(KeyError, 'key not found: :extension')
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
it "raises" do
|
55
|
+
expect { FormatExt.new({:username => "anders"}) }
|
56
|
+
.to raise_error(ArgumentError, /The key 'username'/)
|
57
|
+
|
58
|
+
expect { FormatExt.new("string") }
|
59
|
+
.to raise_error(ArgumentError, "'string' must be a Hash")
|
60
|
+
|
61
|
+
expect { FormatExt.new(:extension => 'value', 'extension' => 'value') }
|
62
|
+
.to raise_error(ArgumentError, "duplicated keys: extension, extension")
|
63
|
+
|
64
|
+
expect { FormatExt.new({:invalid_key => 'invalid' }) }
|
65
|
+
.to raise_error(ArgumentError, /The key 'invalid_key' is not valid/)
|
66
|
+
|
67
|
+
expect { FormatExt.new({:extension => 'value' }).fetch(:invalid_key) }
|
68
|
+
.to raise_error(ArgumentError, /The key 'invalid_key' is not valid/)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'resto/format'
|
5
|
+
|
6
|
+
describe "Resto::Format.get" do
|
7
|
+
subject { Resto::Format.get }
|
8
|
+
|
9
|
+
its(:extension) { should == nil }
|
10
|
+
its(:accept) { should == '*/*' }
|
11
|
+
its(:content_type) { should == nil }
|
12
|
+
describe ".encode(text)" do
|
13
|
+
it("returns text") do
|
14
|
+
subject.encode('very important').should == 'very important'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe ".decode(text)" do
|
19
|
+
it("returns text") do
|
20
|
+
subject.encode('somehting important').should == 'somehting important'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'resto/format'
|
5
|
+
require 'yajl'
|
6
|
+
|
7
|
+
describe "Resto::Format.get(:json)" do
|
8
|
+
subject { Resto::Format.get(:json) }
|
9
|
+
|
10
|
+
its(:extension) { should == 'json' }
|
11
|
+
its(:accept) { should == 'application/json, */*' }
|
12
|
+
its(:content_type) { should == 'application/json' }
|
13
|
+
|
14
|
+
describe ".encode(hash)" do
|
15
|
+
before { @result = subject.encode({ :bar => "some string",
|
16
|
+
:foo => 12425125}) }
|
17
|
+
|
18
|
+
it { @result.should =~ /bar\":\"some string/ }
|
19
|
+
it { @result.should =~ /foo\":12425125/ }
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '.decode(json)' do
|
23
|
+
json = Yajl::Encoder.encode( { :foo => 12425125, :bar => "some string" })
|
24
|
+
expected = { 'foo' => 12425125, 'bar' => "some string" }
|
25
|
+
|
26
|
+
it { subject.decode(json).should == expected }
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'resto/format'
|
5
|
+
|
6
|
+
describe "Resto::Format.get(:plain)" do
|
7
|
+
subject { Resto::Format.get(:plain) }
|
8
|
+
|
9
|
+
its(:extension) { should == nil }
|
10
|
+
its(:accept) { should == 'text/plain, */*' }
|
11
|
+
its(:content_type) { should == 'text/plain' }
|
12
|
+
|
13
|
+
context ".encode(text)" do
|
14
|
+
it("returns text") { subject.encode('important').should == 'important' }
|
15
|
+
end
|
16
|
+
|
17
|
+
context ".decode(text)" do
|
18
|
+
it("returns text") { subject.encode('important').should == 'important' }
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'resto/format'
|
5
|
+
|
6
|
+
describe "Resto::Format.get(:xml)" do
|
7
|
+
subject { Resto::Format.get(:xml) }
|
8
|
+
|
9
|
+
its(:extension) { should == 'xml' }
|
10
|
+
its(:accept) { should == 'application/xml, */*' }
|
11
|
+
its(:content_type) { should == 'application/xml;charset=utf-8' }
|
12
|
+
|
13
|
+
let(:hash) do
|
14
|
+
{:zone =>
|
15
|
+
{ 'default-ttl' => 600,
|
16
|
+
'domain' => "example.com",
|
17
|
+
'ns1' => nil,
|
18
|
+
'ns-type' => "pri_sec",
|
19
|
+
'nx-ttl' => 900,
|
20
|
+
'slave-nameservers' => nil
|
21
|
+
}
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
describe ".encode(hash)" do
|
26
|
+
before { @result = subject.encode(hash) }
|
27
|
+
|
28
|
+
it { @result.should =~ /<\?xml version=\"1.0\"\?>/ }
|
29
|
+
it { @result.should =~ /<zone>.+<\/zone>\Z/m }
|
30
|
+
it { @result.should =~ /<default-ttl>600<\/default-ttl>/ }
|
31
|
+
it { @result.should =~ /<ns1\/>/ }
|
32
|
+
it { @result.should =~ /<slave-nameservers\/>/ }
|
33
|
+
end
|
34
|
+
|
35
|
+
let(:xml) do
|
36
|
+
'<?xml version="1.0"?><zone>
|
37
|
+
<default-ttl>600</default-ttl>
|
38
|
+
<domain>example.com</domain>
|
39
|
+
<ns1/>
|
40
|
+
<ns-type>pri_sec</ns-type>
|
41
|
+
<nx-ttl>900</nx-ttl>
|
42
|
+
<slave-nameservers/>
|
43
|
+
</zone>'
|
44
|
+
end
|
45
|
+
|
46
|
+
let(:xml_collection) do
|
47
|
+
'<?xml version="1.0"?>
|
48
|
+
<zones>
|
49
|
+
<zone>
|
50
|
+
<default-ttl>600</default-ttl>
|
51
|
+
<domain>example.com</domain>
|
52
|
+
<ns1/>
|
53
|
+
<ns-type>pri_sec</ns-type>
|
54
|
+
<nx-ttl>900</nx-ttl>
|
55
|
+
<slave-nameservers/>
|
56
|
+
</zone>
|
57
|
+
<zone>
|
58
|
+
<default-ttl>700</default-ttl>
|
59
|
+
<domain>example.com</domain>
|
60
|
+
<ns1/>
|
61
|
+
<ns-type>pri_sec</ns-type>
|
62
|
+
<nx-ttl>800</nx-ttl>
|
63
|
+
<slave-nameservers/>
|
64
|
+
</zone>
|
65
|
+
</zones>'
|
66
|
+
end
|
67
|
+
|
68
|
+
let(:attributes) do
|
69
|
+
{ 'default-ttl' => "600",
|
70
|
+
'domain' => "example.com",
|
71
|
+
'ns1' => "",
|
72
|
+
'ns-type' => "pri_sec",
|
73
|
+
'nx-ttl' => "900",
|
74
|
+
'slave-nameservers' => ""
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
let(:second_attributes) do
|
79
|
+
{ 'default-ttl' => "700",
|
80
|
+
'domain' => "example.com",
|
81
|
+
'ns1' => "",
|
82
|
+
'ns-type' => "pri_sec",
|
83
|
+
'nx-ttl' => "800",
|
84
|
+
'slave-nameservers' => ""
|
85
|
+
}
|
86
|
+
end
|
87
|
+
|
88
|
+
describe '.decode(xml, xpath)' do
|
89
|
+
context 'when one item' do
|
90
|
+
it { subject.decode(xml, :xpath => '//zone').should == attributes }
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'when 0 items' do
|
94
|
+
it { subject.decode(xml, :xpath => '//xx0').should == {} }
|
95
|
+
end
|
96
|
+
|
97
|
+
context 'when a collection of two items' do
|
98
|
+
it do
|
99
|
+
subject.decode(xml_collection, :xpath => '//zone').should ==
|
100
|
+
[attributes, second_attributes]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|