remote_api 0.1.2 → 0.2.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/Manifest.txt CHANGED
@@ -12,7 +12,9 @@ lib/remote_api/xml_response.rb
12
12
 
13
13
  lib/remote_api/version.rb
14
14
 
15
- test/test_helper.rb
16
- test/base_test.rb
17
- test/xml_test.rb
18
- test/xml_response_test.rb
15
+ test/spec_test.rb
16
+
17
+ spec/base_spec.rb
18
+ spec/spec_helper.rb
19
+ spec/xml_response_spec.rb
20
+ spec/xml_spec.rb
data/README.txt CHANGED
@@ -1,41 +1,112 @@
1
- Simple Readme for now.
1
+ = Remote API
2
2
 
3
3
  Rubyforge Project: http://rubyforge.org/projects/remote-api/
4
4
 
5
- === Installation
5
+ Installation: <tt>gem install remote_api</tt>
6
6
 
7
- gem install remote_api
7
+ == Overview
8
8
 
9
- === Example
9
+ +RemoteAPI+ is an abstraction from API classes. I noticed that there was very overlapping
10
+ functionality in the various API wrappers I had going. This gem will make it much easier to
11
+ write an API wrapper by taking care of the common stuff. All you have to do is write the
12
+ parts that are specific to the API you are talking to.
13
+
14
+ === Usage and Checklist
15
+
16
+ To use this gem you should follow this simple checklist of things that you must implement on
17
+ your own.
18
+
19
+ 1. Create a class that descends from RemoteAPI: <tt>class Foo < RemoteAPI; end</tt>
20
+ 2. Define the url to access with the url dsl_accessor <tt>url 'some url here'</tt>
21
+ 3. Add a +request+ method to your class. This should return the body of your request.
22
+ 4. Add a +assert_response+ method. This method should raise exceptions if the contents
23
+ of <tt>@response</tt> describe a fatal error.
24
+ 5. Add a +process+ method. This parses the API response. It should pull the relevant
25
+ data out of the <tt>@response</tt> object and put it in instance variables.
26
+ 6. Create <tt>attr_reader</tt>s for the instance variables from the +process+ method that
27
+ you want to expose as methods.
28
+
29
+ === Basic Walkthrough
30
+
31
+ I'm going to explain just what happens under the hood of a class that inherits from RemoteAPI.
32
+
33
+ So lets say that I am writing an API to ship a package. It requires address and weight, each
34
+ on their own line in a YAML like format. On success, it returns the tracking number of the
35
+ package. On failure it just says "There was an error!".
36
+
37
+ Here is an API class that can handle that:
10
38
 
11
- This is an example of how to access a little API that allows you to change the title of an object.
12
- The API would return the title, but in Title Case, and we want to capture that.
13
-
14
39
  require 'remote_api'
15
40
 
16
- class MyAPI < RemoteAPI
17
-
18
- attr_reader :title
19
-
20
- url 'http://test.com/posts/change_title'
41
+ class Shipment < RemoteAPI
42
+ attr_reader :tracking_number
43
+ url 'http://test.com/shipments'
21
44
 
22
45
  def request
23
- "title=#{@title}&post_id={@post_id}"
46
+ <<-EOF
47
+ address: #{@address}
48
+ weight: #{@weight}
49
+ EOF
24
50
  end
25
51
 
26
52
  def assert_success
27
- if @response =~ /&?error=(.+?)&?/
28
- raise ResponseFailure, $1
29
- end
53
+ raise ResponseFailure if @response =~ /error/
30
54
  end
31
55
 
32
56
  def process
33
- @title = @response.match(/&?title=(.+?)&?/)[1]
57
+ @tracking_number = @response
34
58
  end
35
59
 
36
60
  end
61
+
62
+ All the magic happens on instantiation. The request is built and sent, and the response is
63
+ processed. It all starts with:
64
+
65
+ Shipment.new(:address => '123 Fake St', :weight => 12)
66
+
67
+ ==== Instantiation
68
+
69
+ The hash passed to +new+ is converted to instance variables. In this case the Shipment instance
70
+ now has <tt>@address</tt> and <tt>@weight</tt> instance variables in it.
71
+
72
+ ==== Building the request
73
+
74
+ The next step is the +request+ method is called. This should return a string, something that can
75
+ be converted to a sttring. This string will be sent out as the request body to the remote server.
76
+
77
+ ==== Sending the request
78
+
79
+ Now that we have built the request, the connection is made to the remote server at the url defined
80
+ by the dsl_accessor +url+. The request is sent with the result of the +request+ method as the body.
81
+ What the server returns is stored in the <tt>@response</tt> variable. This all happens automatically.
82
+
83
+ ==== Assertion of Success
84
+
85
+ Most API's have some sort of error reporting. The <tt>assert_success</tt> method is for raising
86
+ exceptions if the API reports any errors. The ResponseFailure exception is built into RemoteAPI.
87
+ Parse the response to see if it reports errors.
88
+
89
+ ==== Processing the response
90
+
91
+ You must deinfe a +process+ method. This method will parse the response and stuff any needed data into
92
+ instance varibales. In this case, we are simply getting the entire response since that will be the
93
+ only tracking number that we are expecting.
94
+
95
+ ==== Using the result
96
+
97
+ Define a <tt>attr_reader</tt> for each instance variable from the +process+ you want exposed. Then use
98
+ your new object as you would any other object
99
+
100
+ pkg = Shipment.new(:address => '123 Fake St', :weight => 12)
101
+ puts "Sucess! Your tracking number is #{pkg.tracking_number}"
37
102
 
38
- result = MyAPI.new(:post_id => 123, :title => 'hello world')
39
- # API call happens here
103
+ ==== Using the result with Exception handling
104
+
105
+ You probably don't want your whole app to crash if there is an API error. This is why ruby has exception
106
+ handling
40
107
 
41
- result.title #=> 'Hello World'
108
+ begin
109
+ pkg = Shipment.new(:address => '123 Fake St', :weight => 'foo')
110
+ rescue RemoteAPI::ResponseFailure
111
+ puts "Unable to ship that package. The API really didn't like it."
112
+ end
data/Rakefile CHANGED
@@ -46,4 +46,21 @@ hoe = Hoe.new(GEM_NAME, VERS) do |p|
46
46
  #p.changes - A description of the release's latest changes.
47
47
  p.extra_deps = [['activesupport'], ['dsl_accessor']]
48
48
  #p.spec_extras - A hash of extra values to set in the gemspec.
49
+ end
50
+
51
+ require 'spec/rake/spectask'
52
+ desc "Run all specifications"
53
+ Spec::Rake::SpecTask.new('spec') do |t|
54
+ t.spec_files = FileList['spec/**/*.rb']
55
+ end
56
+
57
+ desc "Run all specification with spec output"
58
+ Spec::Rake::SpecTask.new('spec_print') do |t|
59
+ t.spec_files = FileList['spec/**/*.rb']
60
+ t.spec_opts = ["-f", "s"]
61
+ end
62
+
63
+ desc "Tell you to run specs instead of tests"
64
+ task :test do
65
+ puts "This gem has specs, not tests. Run 'rake spec' or 'rake spec_print' instead"
49
66
  end
@@ -1,42 +1,71 @@
1
1
  class RemoteAPI
2
2
  class ResponseFailure < RuntimeError; end
3
3
 
4
- dsl_accessor :debug
4
+ dsl_accessor :debug
5
5
  dsl_accessor :log_file
6
6
  dsl_accessor :url
7
7
  dsl_accessor :content_type
8
-
9
- class ResponseFailure < RuntimeError; end
10
8
 
11
- # Eeverything happens on instantiation. Pass in a hash, and each key in the hash will
12
- # become an instance variable for use in the rest of the instance methods.
9
+ class ResponseFailure < RuntimeError; end
10
+
11
+ # Prepare a new API object. This will not make the actual remote
12
+ # call until the +call+ method is used. To execute the API call
13
+ # immediately, use the +call+ class method.
14
+ #
15
+ # Any options you pass in as a hash will be created as instance
16
+ # variables. So the below example will have an instance variable
17
+ # <tt>@foo</tt> in the generated API object.
18
+ #
19
+ # api = MyApi.new(:foo => 'bar')
20
+ # api.call
21
+ # api.some_result #=> "You said bar!"
13
22
  #
14
- # Then we send the request, assert that is the response is successful, and process the
15
- # response.
16
23
  def initialize(params = {})
17
24
  params.each do |k, v|
18
25
  instance_variable_set "@#{k}", v
19
26
  end
20
-
21
- send_request
22
- assert_success
23
- process
27
+ end
28
+
29
+ # Instatiate and call the API in one step.
30
+ #
31
+ # api = MyApi.call(:foo => 'bar')
32
+ # api.some_result #=> "You said bar!"
33
+ #
34
+ def self.call(params = {})
35
+ returning new(params) do |api|
36
+ api.call
37
+ end
38
+ end
39
+
40
+ # Execute an instance of an API object that has not been sent to the
41
+ # remote server yet.
42
+ #
43
+ # api = MyApi.new(:foo => 'bar')
44
+ # api.call
45
+ # api.some_result #=> "You said bar!"
46
+ #
47
+ def call
48
+ returning self do
49
+ send_request
50
+ assert_success
51
+ process
52
+ end
24
53
  end
25
54
 
26
55
  private
27
56
 
28
- # Send the request to the UPS servers
57
+ # Send the request to the remote servers
29
58
  def send_request(request_body = nil)
30
59
  request_body ||= request
31
60
  debug_request(request_body)
32
61
 
33
62
  # Setup HTTP objects
34
- url = URI.parse(server_url)
35
- http = Net::HTTP.new(url.host, url.port)
63
+ url = URI.parse(server_url)
64
+ http = Net::HTTP.new(url.host, url.port)
36
65
 
37
66
  if url.is_a?(URI::HTTPS)
38
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
39
- http.use_ssl = true
67
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
68
+ http.use_ssl = true
40
69
  end
41
70
 
42
71
  # Setup request options
@@ -49,28 +78,30 @@ class RemoteAPI
49
78
 
50
79
  # Convert response to proper format
51
80
  @response = prepare_response(response)
52
-
53
- # Code hook to raise execption if error conditions are met
81
+
82
+ # Code hook to raise execption if error conditions are met
54
83
  assert_success
55
84
  end
56
85
 
57
- def assert_success
58
- true
59
- end
86
+ # override this method and raises exception on failure
87
+ def assert_success; end
60
88
 
89
+ # override this method to parse your response
61
90
  def process
62
- raise 'You must define a "process" method! This should should parse the @response and' +
63
- 'extract relevant data.'
64
- end
65
-
66
- def request
67
- raise 'You must define a "request" method! This should create the body of your API request'
91
+ raise 'You must define a "process" method! This should should parse the @response and extract relevant data.'
92
+ end
93
+
94
+ # override this method to define your request body
95
+ def request
96
+ raise 'You must define a "request" method! This should create the body of your API request'
68
97
  end
69
98
 
99
+ # Convert response to proper format
70
100
  def prepare_response(response)
71
101
  response.body
72
102
  end
73
103
 
104
+ # Get the full path to the remote server
74
105
  def server_url
75
106
  url = self.class.url
76
107
 
@@ -78,7 +109,11 @@ class RemoteAPI
78
109
  when 'String'
79
110
  url
80
111
  when 'Hash'
81
- url.symbolize_keys[ENV['RAILS_ENV'].to_sym]
112
+ if env = ENV['RAILS_ENV']
113
+ url.symbolize_keys[ENV['RAILS_ENV'].to_sym]
114
+ else
115
+ raise 'Cannot use a hash for server url outside of a rails environment'
116
+ end
82
117
  when 'Proc'
83
118
  url.call
84
119
  else
@@ -86,16 +121,17 @@ class RemoteAPI
86
121
  end
87
122
  end
88
123
 
124
+ # Convert reponse to proper format
89
125
  def format_response(response)
90
126
  response
91
127
  end
92
-
93
- def log(data)
94
- data = "\n\n\n\n\n*** #{Time.now}\n\n" + data
95
- if file = self.class.log_file
96
- File.open(file, 'a') { |f| f.write data }
97
- end
98
- end
128
+
129
+ def log(data)
130
+ data = "\n\n\n\n\n*** #{Time.now}\n\n" + data
131
+ if file = self.class.log_file
132
+ File.open(file, 'a') { |f| f.write data }
133
+ end
134
+ end
99
135
 
100
136
  def debug_request(request_body)
101
137
  return unless self.class.debug || self.class.log_file
@@ -106,8 +142,8 @@ class RemoteAPI
106
142
  -----------
107
143
 
108
144
  #{request_body}
109
- DEBUG
110
- puts text if self.class.debug
145
+ DEBUG
146
+ puts text if self.class.debug
111
147
  log(text) if self.class.log_file
112
148
  end
113
149
 
@@ -125,9 +161,9 @@ DEBUG
125
161
 
126
162
  #{text}
127
163
 
128
- DEBUG
129
-
130
- puts text if self.class.debug
164
+ DEBUG
165
+
166
+ puts text if self.class.debug
131
167
  log(text) if self.class.log_file
132
168
  end
133
169
  end
@@ -1,8 +1,8 @@
1
1
  class RemoteAPI #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 1
5
- TINY = 2
4
+ MINOR = 2
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
data/lib/remote_api.rb CHANGED
@@ -8,6 +8,6 @@ require 'active_support'
8
8
  require 'dsl_accessor'
9
9
 
10
10
  # remote_api
11
- require 'remote_api/base'
12
- require 'remote_api/xml'
13
- require 'remote_api/xml_response'
11
+ %w( base xml xml_response ).each do |file|
12
+ require File.dirname(__FILE__) + '/remote_api/' + file
13
+ end
data/spec/base_spec.rb ADDED
@@ -0,0 +1,65 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ FakeWeb.register_uri(
4
+ 'http://test.com/base',
5
+ :string => '<server_response>The server recieved your message</server_response>'
6
+ )
7
+ FakeWeb.register_uri(
8
+ 'http://test.com/base/error',
9
+ :string => '<server_response>An error occurred!</server_response>'
10
+ )
11
+
12
+ context "A Generic API" do
13
+
14
+ setup do
15
+ BaseApi.url = 'http://test.com/base'
16
+ end
17
+
18
+ specify "'initialize'_should_set_hash_keys_as_instance_variables" do
19
+ api = BaseApi.new(:foo => 'bar', :baz => 'taz', :message => 'Hello')
20
+
21
+ api.instance_eval { @foo }.should_be == 'bar'
22
+ api.instance_eval { @baz }.should_be == 'taz'
23
+ api.instance_eval { @message }.should_be == 'Hello'
24
+ end
25
+
26
+ specify "instance method 'call' should perform API call" do
27
+ api = BaseApi.new(:message => 'Hello World!')
28
+ api.return_message.should_be_nil
29
+
30
+ api.call
31
+ api.return_message.should_be == 'The server recieved your message'
32
+ end
33
+
34
+ specify "class method 'call' should instantiate and call API" do
35
+ api = BaseApi.call(:message => 'Hello World!')
36
+ api.return_message.should_be == 'The server recieved your message'
37
+ end
38
+
39
+ specify "'assert_success' should raise and exception on an error" do
40
+ BaseApi.url = 'http://test.com/base/error'
41
+ proc { BaseApi.call(:message => 'foo') }.should_raise RemoteAPI::ResponseFailure
42
+ end
43
+
44
+ end
45
+
46
+
47
+ class BaseApi < RemoteAPI
48
+ attr_reader :return_message
49
+
50
+ def request
51
+ x = Builder::XmlMarkup.new
52
+ x.my_request @message
53
+ end
54
+
55
+ def assert_success
56
+ if @response =~ %r{<server_response>(.*error.*)</server_response>}
57
+ raise ResponseFailure, $1
58
+ end
59
+ end
60
+
61
+ def process
62
+ @return_message = @response.gsub(%r{</?server_response>}, '')
63
+ end
64
+
65
+ end
@@ -1,5 +1,3 @@
1
- require 'test/unit'
2
-
3
1
  require 'rubygems'
4
2
  require 'fake_web'
5
3
  require 'builder'
@@ -0,0 +1,77 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ context "An XML Response object" do
4
+
5
+ XML = <<XML
6
+ <response>
7
+ <title>Test Title</title>
8
+ <items>
9
+ <item>
10
+ <name>Bob</name>
11
+ <id>1</id>
12
+ </item>
13
+ <item>
14
+ <name>Joe</name>
15
+ <id>2</id>
16
+ </item>
17
+ <item>
18
+ <name>Walter</name>
19
+ <id>3</id>
20
+ </item>
21
+ </items>
22
+ </response>
23
+ XML
24
+
25
+ setup do
26
+ @xml = RemoteAPI::XML::Response.new(XML)
27
+ end
28
+
29
+ specify "[] should accept XPath" do
30
+ @xml['//title'].should_be == "Test Title"
31
+ end
32
+
33
+ specify "a bad XPath passed to [] should return nil" do
34
+ @xml['/foo/bar/baz'].should_be_nil
35
+ end
36
+
37
+ specify "'each' with a bad XPath should not run provided block" do
38
+ count = 0
39
+ @xml.each('/foo/bar/baz') { |node| count += 1 }
40
+ count.should_be_zero
41
+ end
42
+
43
+ specify "'each' should execute block for every matching XPath" do
44
+ expected_names = %w( Bob Joe Walter )
45
+ expected_ids = %w( 1 2 3 )
46
+ count = 0
47
+
48
+ @xml.each "//items/item" do |node|
49
+ count += 1
50
+ node['name'].should_be == expected_names.shift
51
+ node['id'].should_be == expected_ids.shift
52
+ end
53
+
54
+ count.should_be == 3
55
+ end
56
+
57
+ specify "calling 'each' without a block should raise an ArgumentError" do
58
+ proc {
59
+ @xml.each('//title')
60
+ }.should_raise ArgumentError
61
+ end
62
+
63
+ specify "'to_formatted_s' should make the xml pretty" do
64
+ input = '<a><b><c>foo</c></b></a>'
65
+ expected = <<XML
66
+ <a>
67
+ <b>
68
+ <c>foo</c>
69
+ </b>
70
+ </a>
71
+ XML
72
+ xml_response = RemoteAPI::XML::Response.new(input)
73
+
74
+ xml_response.to_formatted_s.should_be == expected.chomp
75
+ end
76
+
77
+ end
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/test_helper.rb'
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
2
 
3
3
  FakeWeb.register_uri(
4
4
  'http://test.com/xml',
@@ -8,56 +8,54 @@ FakeWeb.register_uri(
8
8
  'http://test.com/xml/error',
9
9
  :string => '<server_response><error>Big fat error</error></server_response>'
10
10
  )
11
+
12
+ class XmlApi < RemoteAPI::XML
13
+ attr_reader :return_message
14
+
15
+ def request
16
+ x = Builder::XmlMarkup.new
17
+ x.my_request @message
18
+ end
19
+
20
+ def assert_success
21
+ if error = @response['/server_response/error']
22
+ raise ResponseFailure, error
23
+ end
24
+ end
25
+
26
+ def process
27
+ @return_message = @response['/foo/server_response']
28
+ end
29
+ end
30
+
11
31
 
12
- class RemoteApiXMLTest < Test::Unit::TestCase
32
+ context "An XML API" do
13
33
 
14
- def setup
34
+ setup do
15
35
  XmlApi.url = 'http://test.com/xml'
16
36
  end
17
37
 
18
- def test_response_should_be_xml
19
- result = XmlApi.new(:message => 'foo')
20
- assert_equal('The server recieved your message', result.return_message)
38
+ specify "response should be XML" do
39
+ result = XmlApi.call(:message => 'foo')
40
+ result.return_message.should_be == 'The server recieved your message'
21
41
  end
22
42
 
23
- def test_format_response_should_produce_pretty_xml
43
+ specify "'format_response' should produce pretty xml" do
24
44
  expected = <<XML
25
45
  <foo>
26
46
  <server_response>The server recieved your message</server_response>
27
47
  </foo>
28
48
  XML
29
49
 
30
- result = XmlApi.new(:message => 'foo')
31
- data = result.send(:format_response, '<foo><server_response>The server recieved your message</server_response></foo>')
32
- assert_equal(expected.chomp, data)
50
+ result = XmlApi.call(:message => 'foo')
51
+ data = result.send(:format_response, '<foo><server_response>The server recieved your message</server_response></foo>')
52
+
53
+ data.should_be == expected.chomp
33
54
  end
34
55
 
35
- def test_assert_success_should_raise_exceptions
56
+ specify "'assert_success' should raise an exception on failure" do
36
57
  XmlApi.url = 'http://test.com/xml/error'
37
- assert_raise RemoteAPI::ResponseFailure do
38
- XmlApi.new(:message => 'foo')
39
- end
58
+ proc { XmlApi.call(:message => 'foo') }.should_raise RemoteAPI::ResponseFailure
40
59
  end
41
60
 
42
- end
43
-
44
-
45
- class XmlApi < RemoteAPI::XML
46
- attr_reader :return_message
47
-
48
- def request
49
- x = Builder::XmlMarkup.new
50
- x.my_request @message
51
- end
52
-
53
- def assert_success
54
- if error = @response['/server_response/error']
55
- raise ResponseFailure, error
56
- end
57
- end
58
-
59
- def process
60
- @return_message = @response['/foo/server_response']
61
- end
62
-
63
61
  end
data/test/spec_test.rb ADDED
@@ -0,0 +1,19 @@
1
+ require 'test/unit'
2
+
3
+ class SpecTest < Test::Unit::TestCase
4
+ def test_true
5
+ assert true
6
+ end
7
+ end
8
+
9
+ puts <<SPEC
10
+
11
+ ----------------------------------------------
12
+ This gem has no tests. Please run 'rake spec'
13
+ or 'rake spec_print' instead.
14
+
15
+ The rspec gem must be installed to run specs.
16
+ gem install rspec
17
+ ----------------------------------------------
18
+
19
+ SPEC
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.1
3
3
  specification_version: 1
4
4
  name: remote_api
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.2
7
- date: 2007-01-17 00:00:00 -08:00
6
+ version: 0.2.0
7
+ date: 2007-04-19 00:00:00 -07:00
8
8
  summary: Provides a basic framework for easily creating classes that access remote APIs.
9
9
  require_paths:
10
10
  - lib
@@ -39,14 +39,13 @@ files:
39
39
  - lib/remote_api/xml.rb
40
40
  - lib/remote_api/xml_response.rb
41
41
  - lib/remote_api/version.rb
42
- - test/test_helper.rb
43
- - test/base_test.rb
44
- - test/xml_test.rb
45
- - test/xml_response_test.rb
42
+ - test/spec_test.rb
43
+ - spec/base_spec.rb
44
+ - spec/spec_helper.rb
45
+ - spec/xml_response_spec.rb
46
+ - spec/xml_spec.rb
46
47
  test_files:
47
- - test/base_test.rb
48
- - test/xml_response_test.rb
49
- - test/xml_test.rb
48
+ - test/spec_test.rb
50
49
  rdoc_options: []
51
50
 
52
51
  extra_rdoc_files: []
data/test/base_test.rb DELETED
@@ -1,58 +0,0 @@
1
- require File.dirname(__FILE__) + '/test_helper.rb'
2
-
3
- FakeWeb.register_uri(
4
- 'http://test.com/base',
5
- :string => '<server_response>The server recieved your message</server_response>'
6
- )
7
- FakeWeb.register_uri(
8
- 'http://test.com/base/error',
9
- :string => '<server_response>An error occurred!</server_response>'
10
- )
11
-
12
- class RemoteApiTest < Test::Unit::TestCase
13
-
14
- def setup
15
- BaseApi.url = 'http://test.com/base'
16
- end
17
-
18
- def test_initialize_should_set_hash_keys_as_instance_variables
19
- result = BaseApi.new(:foo => 'bar', :baz => 'taz', :message => 'Hello')
20
-
21
- assert_equal('bar', result.instance_eval { @foo })
22
- assert_equal('taz', result.instance_eval { @baz })
23
- assert_equal('Hello', result.instance_eval { @message })
24
- end
25
-
26
- def test_initialize_should_perform_api_call
27
- result = BaseApi.new(:message => 'Hello World!')
28
- assert_equal 'The server recieved your message', result.return_message
29
- end
30
-
31
- def test_assert_success_should_raise_exception
32
- BaseApi.url = 'http://test.com/base/error'
33
- assert_raise RemoteAPI::ResponseFailure do
34
- BaseApi.new(:message => 'foo')
35
- end
36
- end
37
- end
38
-
39
-
40
- class BaseApi < RemoteAPI
41
- attr_reader :return_message
42
-
43
- def request
44
- x = Builder::XmlMarkup.new
45
- x.my_request @message
46
- end
47
-
48
- def assert_success
49
- if @response =~ %r{<server_response>(.*error.*)</server_response>}
50
- raise ResponseFailure, $1
51
- end
52
- end
53
-
54
- def process
55
- @return_message = @response.gsub(%r{</?server_response>}, '')
56
- end
57
-
58
- end
@@ -1,77 +0,0 @@
1
- require File.dirname(__FILE__) + '/test_helper.rb'
2
-
3
- class XmlResponseTest < Test::Unit::TestCase
4
-
5
- XML = <<XML
6
- <response>
7
- <title>Test Title</title>
8
- <items>
9
- <item>
10
- <name>Bob</name>
11
- <id>1</id>
12
- </item>
13
- <item>
14
- <name>Joe</name>
15
- <id>2</id>
16
- </item>
17
- <item>
18
- <name>Walter</name>
19
- <id>3</id>
20
- </item>
21
- </items>
22
- </response>
23
- XML
24
-
25
- def setup
26
- @xml = RemoteAPI::XML::Response.new(XML)
27
- end
28
-
29
- def test_brace_accessor
30
- assert_equal('Test Title', @xml['//title'])
31
- end
32
-
33
- def test_bad_xpath_should_return_nil
34
- assert_nil @xml['/foo/bar/baz']
35
- end
36
-
37
- def test_each_on_bad_xpath_should_not_run_block
38
- count = 0
39
- @xml.each('/foo/bar/baz') { |node| count += 1 }
40
- assert_equal(0, count)
41
- end
42
-
43
- def test_each
44
- expected_names = %w( Bob Joe Walter )
45
- expected_ids = %w( 1 2 3 )
46
- count = 0
47
-
48
- @xml.each '//items/item' do |node|
49
- count += 1
50
- assert_equal(expected_names.shift, node['name'])
51
- assert_equal(expected_ids.shift, node['id'])
52
- end
53
-
54
- assert_equal(3, count)
55
- end
56
-
57
- def test_each_without_block_should_raise_exception
58
- assert_raise(ArgumentError) do
59
- @xml.each('//title')
60
- end
61
- end
62
-
63
- def test_to_formatted_s
64
- input = '<a><b><c>foo</c></b></a>'
65
- expected = <<XML
66
- <a>
67
- <b>
68
- <c>foo</c>
69
- </b>
70
- </a>
71
- XML
72
- xml_response = RemoteAPI::XML::Response.new(input)
73
-
74
- assert_equal(expected.chomp, xml_response.to_formatted_s)
75
- end
76
-
77
- end