resto 0.0.3 → 0.0.4
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/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
|