glennr_opensrs 0.3.3
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/.document +5 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +33 -0
- data/LICENSE +20 -0
- data/README.rdoc +97 -0
- data/Rakefile +40 -0
- data/lib/opensrs.rb +8 -0
- data/lib/opensrs/response.rb +29 -0
- data/lib/opensrs/server.rb +77 -0
- data/lib/opensrs/version.rb +5 -0
- data/lib/opensrs/xml_processor.rb +77 -0
- data/lib/opensrs/xml_processor/libxml.rb +60 -0
- data/lib/opensrs/xml_processor/nokogiri.rb +59 -0
- data/opensrs.gemspec +76 -0
- data/spec/opensrs/server_spec.rb +109 -0
- data/spec/opensrs/version_spec.rb +9 -0
- data/spec/opensrs/xml_processor/libxml_spec.rb +254 -0
- data/spec/opensrs/xml_processor/nokogiri_spec.rb +228 -0
- data/spec/spec_helper.rb +6 -0
- metadata +182 -0
@@ -0,0 +1,59 @@
|
|
1
|
+
begin
|
2
|
+
require 'nokogiri'
|
3
|
+
rescue LoadError => e
|
4
|
+
$stderr.puts "Cannot find Nokogiri gem. Please install Nokogiri before using it as the xml processor\n\n"
|
5
|
+
raise e
|
6
|
+
end
|
7
|
+
|
8
|
+
module OpenSRS
|
9
|
+
class XmlProcessor::Nokogiri < OpenSRS::XmlProcessor
|
10
|
+
|
11
|
+
def self.build(data)
|
12
|
+
builder = ::Nokogiri::XML::Builder.new
|
13
|
+
|
14
|
+
envelope = ::Nokogiri::XML::Node.new("OPS_envelope", builder.doc)
|
15
|
+
header = ::Nokogiri::XML::Node.new("header", builder.doc)
|
16
|
+
version = ::Nokogiri::XML::Node.new("version", builder.doc)
|
17
|
+
body = ::Nokogiri::XML::Node.new("body", builder.doc)
|
18
|
+
data_block = ::Nokogiri::XML::Node.new("data_block", builder.doc)
|
19
|
+
other_data = encode_data(data, builder.doc)
|
20
|
+
builder.doc << envelope << header << version << '0.9'
|
21
|
+
envelope << body << data_block << other_data
|
22
|
+
return builder.to_xml
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
def self.data_block_element(response)
|
28
|
+
doc = ::Nokogiri::XML(response)
|
29
|
+
return doc.xpath('//OPS_envelope/body/data_block/*')
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.decode_dt_array_data(element)
|
33
|
+
dt_array = []
|
34
|
+
|
35
|
+
element.children.each do |item|
|
36
|
+
next if item.content.strip.empty?
|
37
|
+
dt_array[item.attributes["key"].value.to_i] = decode_data(item.children)
|
38
|
+
end
|
39
|
+
|
40
|
+
return dt_array
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.decode_dt_assoc_data(element)
|
44
|
+
dt_assoc = {}
|
45
|
+
|
46
|
+
element.children.each do |item|
|
47
|
+
next if item.content.strip.empty?
|
48
|
+
dt_assoc[item.attributes["key"].value] = decode_data(item.children)
|
49
|
+
end
|
50
|
+
|
51
|
+
return dt_assoc
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.new_element(element_name, container)
|
55
|
+
return ::Nokogiri::XML::Node.new(element_name.to_s, container)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
data/opensrs.gemspec
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "opensrs"
|
8
|
+
s.version = "0.3.3"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Josh Delsman", "Glenn Roberts"]
|
12
|
+
s.date = "2013-03-11"
|
13
|
+
s.description = "Provides support to utilize the OpenSRS API with Ruby/Rails."
|
14
|
+
s.email = "jdelsman@voxxit.com"
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
"Gemfile",
|
22
|
+
"Gemfile.lock",
|
23
|
+
"LICENSE",
|
24
|
+
"README.rdoc",
|
25
|
+
"Rakefile",
|
26
|
+
"lib/opensrs.rb",
|
27
|
+
"lib/opensrs/response.rb",
|
28
|
+
"lib/opensrs/server.rb",
|
29
|
+
"lib/opensrs/version.rb",
|
30
|
+
"lib/opensrs/xml_processor.rb",
|
31
|
+
"lib/opensrs/xml_processor/libxml.rb",
|
32
|
+
"lib/opensrs/xml_processor/nokogiri.rb",
|
33
|
+
"opensrs.gemspec",
|
34
|
+
"spec/opensrs/server_spec.rb",
|
35
|
+
"spec/opensrs/version_spec.rb",
|
36
|
+
"spec/opensrs/xml_processor/libxml_spec.rb",
|
37
|
+
"spec/opensrs/xml_processor/nokogiri_spec.rb",
|
38
|
+
"spec/spec_helper.rb"
|
39
|
+
]
|
40
|
+
s.homepage = "http://github.com/voxxit/opensrs"
|
41
|
+
s.licenses = ["MIT"]
|
42
|
+
s.require_paths = ["lib"]
|
43
|
+
s.rubygems_version = "1.8.23"
|
44
|
+
s.summary = "Provides support to utilize the OpenSRS API with Ruby/Rails."
|
45
|
+
|
46
|
+
if s.respond_to? :specification_version then
|
47
|
+
s.specification_version = 3
|
48
|
+
|
49
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
50
|
+
s.add_runtime_dependency(%q<libxml-ruby>, ["~> 2.1.2"])
|
51
|
+
s.add_development_dependency(%q<nokogiri>, ["~> 1.4.6"])
|
52
|
+
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
53
|
+
s.add_development_dependency(%q<git>, [">= 0"])
|
54
|
+
s.add_development_dependency(%q<rake>, [">= 0"])
|
55
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
56
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.0"])
|
57
|
+
else
|
58
|
+
s.add_dependency(%q<libxml-ruby>, ["~> 2.1.2"])
|
59
|
+
s.add_dependency(%q<nokogiri>, ["~> 1.4.6"])
|
60
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
61
|
+
s.add_dependency(%q<git>, [">= 0"])
|
62
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
63
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
64
|
+
s.add_dependency(%q<rspec>, ["~> 2.0"])
|
65
|
+
end
|
66
|
+
else
|
67
|
+
s.add_dependency(%q<libxml-ruby>, ["~> 2.1.2"])
|
68
|
+
s.add_dependency(%q<nokogiri>, ["~> 1.4.6"])
|
69
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
70
|
+
s.add_dependency(%q<git>, [">= 0"])
|
71
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
72
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
73
|
+
s.add_dependency(%q<rspec>, ["~> 2.0"])
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe OpenSRS::Server do
|
4
|
+
let(:server) { OpenSRS::Server.new }
|
5
|
+
|
6
|
+
describe '#new' do
|
7
|
+
it 'allows timeouts to be set' do
|
8
|
+
server = OpenSRS::Server.new({ :timeout => 90 })
|
9
|
+
server.timeout.should == 90
|
10
|
+
server.open_timeout.should be_nil
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'allows open timeouts to be set' do
|
14
|
+
server = OpenSRS::Server.new({ :timeout => 90, :open_timeout => 10 })
|
15
|
+
server.timeout.should eq(90)
|
16
|
+
server.open_timeout.should eq(10)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'leaves it up to Net::HTTP if no timeouts given' do
|
20
|
+
server.timeout.should be_nil
|
21
|
+
server.open_timeout.should be_nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe ".call" do
|
26
|
+
let(:response) { double(:body => 'some response') }
|
27
|
+
let(:header) { {"some" => "header" } }
|
28
|
+
let(:xml) { '<some xml></some xml>' }
|
29
|
+
let(:response_xml) { xml }
|
30
|
+
let(:xml_processor) { double OpenSRS::XmlProcessor }
|
31
|
+
let(:http) { double(Net::HTTP, :use_ssl= => true, :verify_mode= => true) }
|
32
|
+
|
33
|
+
before :each do
|
34
|
+
server.stub(:headers).and_return header
|
35
|
+
xml_processor.stub(:build).and_return xml
|
36
|
+
xml_processor.stub(:parse).and_return response_xml
|
37
|
+
server.stub(:xml_processor).and_return xml_processor
|
38
|
+
http.stub(:post).and_return response
|
39
|
+
Net::HTTP.stub(:new).and_return http
|
40
|
+
end
|
41
|
+
|
42
|
+
it "builds XML request" do
|
43
|
+
xml_processor.should_receive(:build).with(:protocol => "XCP", :some => 'option')
|
44
|
+
server.call(:some => 'option')
|
45
|
+
end
|
46
|
+
|
47
|
+
it "posts to given path" do
|
48
|
+
server.server = URI.parse 'http://with-path.com/endpoint'
|
49
|
+
http.should_receive(:post).with('/endpoint', xml, header).and_return double.as_null_object
|
50
|
+
server.call
|
51
|
+
end
|
52
|
+
|
53
|
+
it "parses the response" do
|
54
|
+
xml_processor.should_receive(:parse).with(response.body)
|
55
|
+
server.call(:some => 'option')
|
56
|
+
end
|
57
|
+
|
58
|
+
it "posts to root path" do
|
59
|
+
server.server = URI.parse 'http://root-path.com/'
|
60
|
+
http.should_receive(:post).with('/', xml, header).and_return double.as_null_object
|
61
|
+
server.call
|
62
|
+
end
|
63
|
+
|
64
|
+
it "defaults path to '/'" do
|
65
|
+
server.server = URI.parse 'http://no-path.com'
|
66
|
+
http.should_receive(:post).with('/', xml, header).and_return double.as_null_object
|
67
|
+
server.call
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'allows overriding of default (Net:HTTP) timeouts' do
|
71
|
+
server.timeout = 90
|
72
|
+
|
73
|
+
http.should_receive(:open_timeout=).with(90)
|
74
|
+
http.should_receive(:read_timeout=).with(90)
|
75
|
+
|
76
|
+
server.call( { :some => 'data' } )
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'allows overriding of default (Net:HTTP) timeouts' do
|
80
|
+
server.timeout = 180
|
81
|
+
server.open_timeout = 30
|
82
|
+
|
83
|
+
http.should_receive(:read_timeout=).with(180)
|
84
|
+
http.should_receive(:open_timeout=).with(180)
|
85
|
+
http.should_receive(:open_timeout=).with(30)
|
86
|
+
|
87
|
+
server.call( { :some => 'data' } )
|
88
|
+
end
|
89
|
+
|
90
|
+
it 're-raises Net:HTTP timeouts' do
|
91
|
+
http.should_receive(:post).and_raise err = Timeout::Error.new('test')
|
92
|
+
expect { server.call }.to raise_exception OpenSRS::TimeoutError
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "#test xml processor" do
|
97
|
+
context "on class initialization" do
|
98
|
+
it { server.xml_processor.should eql(OpenSRS::XmlProcessor::Libxml) }
|
99
|
+
end
|
100
|
+
|
101
|
+
context "on changing xml processor" do
|
102
|
+
before(:each) do
|
103
|
+
OpenSRS::Server.xml_processor = :nokogiri
|
104
|
+
end
|
105
|
+
|
106
|
+
it { server.xml_processor.should eql(OpenSRS::XmlProcessor::Nokogiri) }
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,254 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
describe OpenSRS::XmlProcessor::Libxml do
|
5
|
+
describe ".build" do
|
6
|
+
it "should create XML for a nested hash" do
|
7
|
+
attributes = {:foo => {:bar => 'baz'}}
|
8
|
+
xml = OpenSRS::XmlProcessor::Libxml.build(attributes)
|
9
|
+
xml.should eq %{<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<OPS_envelope>\n <header>\n <version>0.9</version>\n </header>\n <body>\n <data_block>\n <dt_assoc>\n <item key=\"foo\">\n <dt_assoc>\n <item key=\"bar\">baz</item>\n </dt_assoc>\n </item>\n </dt_assoc>\n </data_block>\n </body>\n</OPS_envelope>\n}
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '.encode_data' do
|
14
|
+
context "on a 3 element array" do
|
15
|
+
before(:each) do
|
16
|
+
@e = OpenSRS::XmlProcessor::Libxml.encode_data([1,2,3])
|
17
|
+
end
|
18
|
+
|
19
|
+
it "is a REXML::Element" do
|
20
|
+
@e.should be_an_instance_of(LibXML::XML::Node)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "is a dt_array" do
|
24
|
+
@e.name.should == 'dt_array'
|
25
|
+
end
|
26
|
+
|
27
|
+
it "has 3 children all called <item>" do
|
28
|
+
@e.should have(3).children
|
29
|
+
@e.children[0].name.should == "item"
|
30
|
+
@e.children[1].name.should == "item"
|
31
|
+
@e.children[2].name.should == "item"
|
32
|
+
end
|
33
|
+
|
34
|
+
it "has children with keys 0, 1 and 2" do
|
35
|
+
@e.children[0].attributes["key"].should == "0"
|
36
|
+
@e.children[1].attributes["key"].should == "1"
|
37
|
+
@e.children[2].attributes["key"].should == "2"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "on a hash" do
|
42
|
+
before(:each) do
|
43
|
+
@e = OpenSRS::XmlProcessor::Libxml.encode_data({:name => "kitteh"})
|
44
|
+
end
|
45
|
+
|
46
|
+
it "is a REXML::Element" do
|
47
|
+
@e.should be_an_instance_of(LibXML::XML::Node)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "is a dt_assoc" do
|
51
|
+
@e.name.should == 'dt_assoc'
|
52
|
+
end
|
53
|
+
|
54
|
+
it "has an <item> child with the right key" do
|
55
|
+
@e.should have(1).children
|
56
|
+
@e.children[0].name.should == 'item'
|
57
|
+
@e.children[0].attributes["key"].should == 'name'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "on a nested hash" do
|
62
|
+
before(:each) do
|
63
|
+
@e = OpenSRS::XmlProcessor::Libxml.encode_data({:suggestion => {:maximum => "10"}})
|
64
|
+
end
|
65
|
+
|
66
|
+
it "is a REXML::Element" do
|
67
|
+
@e.should be_an_instance_of(LibXML::XML::Node)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "is a dt_assoc" do
|
71
|
+
@e.name.should == 'dt_assoc'
|
72
|
+
end
|
73
|
+
|
74
|
+
it "has an <item> child with the correct children" do
|
75
|
+
@e.should have(1).children
|
76
|
+
suggestion = @e.children[0]
|
77
|
+
suggestion.name.should == 'item'
|
78
|
+
suggestion.attributes["key"].should == 'suggestion'
|
79
|
+
|
80
|
+
suggestion.should have(1).children
|
81
|
+
dt_assoc = suggestion.children[0]
|
82
|
+
dt_assoc.name.should == 'dt_assoc'
|
83
|
+
|
84
|
+
dt_assoc.should have(1).children
|
85
|
+
maximum = dt_assoc.children[0]
|
86
|
+
maximum.name.should == 'item'
|
87
|
+
maximum.attributes["key"].should == 'maximum'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context "produces a scalar" do
|
92
|
+
it "from a string" do
|
93
|
+
OpenSRS::XmlProcessor::Libxml.encode_data("cheezburger").to_s.should == "cheezburger"
|
94
|
+
end
|
95
|
+
|
96
|
+
it "from a string with XML characters" do
|
97
|
+
OpenSRS::XmlProcessor::Libxml.encode_data("<smile>").to_s.should == "<smile>"
|
98
|
+
end
|
99
|
+
|
100
|
+
it "from an integer" do
|
101
|
+
OpenSRS::XmlProcessor::Libxml.encode_data(12345).to_s.should == "12345"
|
102
|
+
end
|
103
|
+
|
104
|
+
it "from a date" do
|
105
|
+
date = Date.parse("2010/02/12")
|
106
|
+
OpenSRS::XmlProcessor::Libxml.encode_data(date).to_s.should == "2010-02-12"
|
107
|
+
end
|
108
|
+
|
109
|
+
it "from a symbol" do
|
110
|
+
OpenSRS::XmlProcessor::Libxml.encode_data(:name).to_s.should == "name"
|
111
|
+
end
|
112
|
+
|
113
|
+
it "from true or false" do
|
114
|
+
OpenSRS::XmlProcessor::Libxml.encode_data(true).to_s.should == "true"
|
115
|
+
OpenSRS::XmlProcessor::Libxml.encode_data(false).to_s.should == "false"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe '.parse' do
|
121
|
+
it "should handle scalar values" do
|
122
|
+
xml = %{<?xml version='1.0' encoding='UTF-8' standalone='no' ?>
|
123
|
+
<!DOCTYPE OPS_envelope SYSTEM 'ops.dtd'>
|
124
|
+
<OPS_envelope>
|
125
|
+
<header>
|
126
|
+
<version>1.0</version>
|
127
|
+
</header>
|
128
|
+
<body>
|
129
|
+
<data_block>
|
130
|
+
<dt_scalar>Tom Jones</dt_scalar>
|
131
|
+
</data_block>
|
132
|
+
</body>
|
133
|
+
</OPS_envelope>}
|
134
|
+
|
135
|
+
resp = OpenSRS::XmlProcessor::Libxml.parse(xml)
|
136
|
+
resp.should == "Tom Jones"
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should handle associate arrays with arrays of values" do
|
140
|
+
xml = %{<?xml version='1.0' encoding='UTF-8' standalone='no' ?>
|
141
|
+
<!DOCTYPE OPS_envelope SYSTEM 'ops.dtd'>
|
142
|
+
<OPS_envelope>
|
143
|
+
<header>
|
144
|
+
<version>1.0</version>
|
145
|
+
</header>
|
146
|
+
<body>
|
147
|
+
<data_block>
|
148
|
+
<dt_assoc>
|
149
|
+
<item key='domain_list'>
|
150
|
+
<dt_array>
|
151
|
+
<item key='0'>ns1.example.com</item>
|
152
|
+
<item key='1'>ns2.example.com</item>
|
153
|
+
<item key='2'>ns3.example.com</item>
|
154
|
+
</dt_array>
|
155
|
+
</item>
|
156
|
+
</dt_assoc>
|
157
|
+
</data_block>
|
158
|
+
</body>
|
159
|
+
</OPS_envelope>}
|
160
|
+
|
161
|
+
resp = OpenSRS::XmlProcessor::Libxml.parse(xml)
|
162
|
+
resp["domain_list"].class.should == Array
|
163
|
+
resp["domain_list"][0].should == "ns1.example.com"
|
164
|
+
resp["domain_list"][1].should == "ns2.example.com"
|
165
|
+
resp["domain_list"][2].should == "ns3.example.com"
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should handle associative arrays containing other associative arrays" do
|
169
|
+
xml = %{<?xml version='1.0' encoding='UTF-8' standalone='no' ?>
|
170
|
+
<!DOCTYPE OPS_envelope SYSTEM 'ops.dtd'>
|
171
|
+
<OPS_envelope>
|
172
|
+
<header>
|
173
|
+
<version>1.0</version>
|
174
|
+
</header>
|
175
|
+
<body>
|
176
|
+
<data_block>
|
177
|
+
<dt_assoc>
|
178
|
+
<item key="contact_set">
|
179
|
+
<dt_assoc>
|
180
|
+
<item key='owner'>
|
181
|
+
<dt_assoc>
|
182
|
+
<item key='first_name'>Tom</item>
|
183
|
+
<item key='last_name'>Jones</item>
|
184
|
+
</dt_assoc>
|
185
|
+
</item>
|
186
|
+
<item key='tech'>
|
187
|
+
<dt_assoc>
|
188
|
+
<item key='first_name'>Anne</item>
|
189
|
+
<item key='last_name'>Smith</item>
|
190
|
+
</dt_assoc>
|
191
|
+
</item>
|
192
|
+
</dt_assoc>
|
193
|
+
</item>
|
194
|
+
</dt_assoc>
|
195
|
+
</data_block>
|
196
|
+
</body>
|
197
|
+
</OPS_envelope>}
|
198
|
+
|
199
|
+
resp = OpenSRS::XmlProcessor::Libxml.parse(xml)
|
200
|
+
|
201
|
+
resp["contact_set"]["owner"]["first_name"].should == "Tom"
|
202
|
+
resp["contact_set"]["owner"]["last_name"].should == "Jones"
|
203
|
+
resp["contact_set"]["tech"]["first_name"].should == "Anne"
|
204
|
+
resp["contact_set"]["tech"]["last_name"].should == "Smith"
|
205
|
+
end
|
206
|
+
|
207
|
+
context "with a balance enquiry example response" do
|
208
|
+
before(:each) do
|
209
|
+
xml = %{<?xml version='1.0' encoding='UTF-8' standalone='no' ?>
|
210
|
+
<!DOCTYPE OPS_envelope SYSTEM 'ops.dtd'>
|
211
|
+
<OPS_envelope>
|
212
|
+
<header>
|
213
|
+
<version>0.9</version>
|
214
|
+
</header>
|
215
|
+
<body>
|
216
|
+
<data_block>
|
217
|
+
<dt_assoc>
|
218
|
+
<item key="protocol">XCP</item>
|
219
|
+
<item key="action">REPLY</item>
|
220
|
+
<item key="object">BALANCE</item>
|
221
|
+
<item key="is_success">1</item>
|
222
|
+
<item key="response_code">200</item>
|
223
|
+
<item key="response_text">Command successful</item>
|
224
|
+
<item key="attributes">
|
225
|
+
<dt_assoc>
|
226
|
+
<item key="balance">8549.18</item>
|
227
|
+
<item key="hold_balance">1676.05</item>
|
228
|
+
</dt_assoc>
|
229
|
+
</item>
|
230
|
+
</dt_assoc>
|
231
|
+
</data_block>
|
232
|
+
</body>
|
233
|
+
</OPS_envelope>}
|
234
|
+
|
235
|
+
@resp = OpenSRS::XmlProcessor::Libxml.parse(xml)
|
236
|
+
end
|
237
|
+
|
238
|
+
it "produces a hash" do
|
239
|
+
@resp.should be_an_instance_of(Hash)
|
240
|
+
end
|
241
|
+
|
242
|
+
it "has top level keys" do
|
243
|
+
@resp["protocol"].should == "XCP"
|
244
|
+
@resp["action"].should == "REPLY"
|
245
|
+
@resp["object"].should == "BALANCE"
|
246
|
+
end
|
247
|
+
|
248
|
+
it "has second level keys" do
|
249
|
+
@resp["attributes"]["balance"].should == "8549.18"
|
250
|
+
@resp["attributes"]["hold_balance"].should == "1676.05"
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|