smacks-savon 0.1.61 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,173 +0,0 @@
1
- require "rubygems"
2
- require "hpricot"
3
- require "apricoteatsgorilla"
4
-
5
- module Savon
6
-
7
- # Savon::HTTPResponse containes methods exclusive to a Net::HTTPResponse
8
- # to be included in Savon::Response.
9
- module HTTPResponse
10
-
11
- # Returns the error code.
12
- attr_reader :error_code
13
-
14
- # Returns the error message.
15
- attr_reader :error_message
16
-
17
- # Returns +true+ in case the request was successful, +false+ otherwise
18
- # or +nil+ in case there was no request at all.
19
- def success?
20
- return nil unless @response
21
- @error_code.nil?
22
- end
23
-
24
- # Returns +false+ in case the request was not successful, +true+ otherwise
25
- # or +nil+ in case there was no request at all.
26
- def error?
27
- return nil unless @response
28
- !@error_code.nil?
29
- end
30
-
31
- private
32
-
33
- # Validates the response against HTTP errors and SOAP faults and sets the
34
- # +error_code+ and +error_message+ in case the request was not successful.
35
- def validate_response
36
- if @response.code.to_i >= 300
37
- @error_message = @response.message
38
- @error_code = @response.code
39
- else
40
- soap_fault = ApricotEatsGorilla[@response.body, "//soap:Fault"]
41
- unless soap_fault.nil? || soap_fault.empty?
42
- @error_message = soap_fault[:faultstring]
43
- @error_code = soap_fault[:faultcode]
44
- end
45
- end
46
- end
47
-
48
- # Translates the response body into a Hash. Takes an optional +root_node+
49
- # argument to start parsing the response body at a custom root node.
50
- def response_to_hash(root_node = nil)
51
- ApricotEatsGorilla[@response.body, root_node]
52
- end
53
-
54
- end
55
-
56
- # Savon::Response represents the HTTP/SOAP response.
57
- class Response
58
-
59
- include Savon::HTTPResponse
60
-
61
- # The default root node to start parsing the SOAP response at.
62
- @@default_root_node = "//return"
63
-
64
- # Returns the default root node.
65
- def self.default_root_node
66
- @@default_root_node
67
- end
68
-
69
- # Sets the default root node.
70
- def self.default_root_node=(root_node)
71
- @@default_root_node = root_node if root_node.kind_of?(String)
72
- end
73
-
74
- # The core (inherited) methods to shadow.
75
- @@core_methods_to_shadow = [:id]
76
-
77
- # Returns the core methods to shadow.
78
- def self.core_methods_to_shadow
79
- @@core_methods_to_shadow
80
- end
81
-
82
- # Sets the core +methods+ to shadow.
83
- def self.core_methods_to_shadow=(methods)
84
- @@core_methods_to_shadow = methods if methods.kind_of?(Array)
85
- end
86
-
87
- # Initializer expects the +source+ to initialize from. Sets up the instance
88
- # from a given Net::HTTPResponse or a Hash depending on the given +source+.
89
- # May be called with a custom +root_node+ to start parsing the response at
90
- # in case the given +source+ is a Net::HTTPResponse.
91
- def initialize(source, root_node = nil)
92
- if source.kind_of? Hash
93
- initialize_from_hash(source)
94
- elsif source.respond_to? :body
95
- initialize_from_response(source, root_node)
96
- end
97
- end
98
-
99
- # Returns the value from a given +key+ from the response Hash.
100
- def [](key)
101
- return @hash unless @hash.kind_of?(Hash)
102
- value_from_hash(key)
103
- end
104
-
105
- # Returns the response Hash. Takes an optional +root_node+ to start parsing
106
- # the SOAP response at instead of the +@@default_root_node+.
107
- def to_hash(root_node = nil)
108
- return @hash if root_node.nil?
109
- response_to_hash(root_node)
110
- end
111
-
112
- # Returns the response body in case there is any, +nil+ otherwise.
113
- def to_s
114
- return nil unless @response
115
- @response.body
116
- end
117
-
118
- # Intercepts calls to missing methods and returns values from the response
119
- # Hash in case the name of the missing +method+ matches one of its key.
120
- # Returns a new Savon::Response instance containing the value or returns
121
- # the actual value in case it is not a Hash.
122
- def method_missing(method, *args)
123
- return @hash unless @hash.kind_of?(Hash)
124
-
125
- value = value_from_hash(method)
126
- return value unless value.kind_of?(Hash)
127
- Savon::Response.new(value)
128
- end
129
-
130
- private
131
-
132
- # Initializes the instance from a Net::HTTPResponse. Validates the +response+
133
- # against HTTP errors and SOAP faults. Continues to translate the response
134
- # body into a Hash and delegates to initializing the instance from this Hash
135
- # in case the request was successful. An optional +root_node+ to start parsing
136
- # the response at might be supplied.
137
- def initialize_from_response(response, root_node = nil)
138
- @response = response
139
- validate_response
140
-
141
- if success?
142
- root_node ||= @@default_root_node
143
- hash = response_to_hash(root_node)
144
- initialize_from_hash(hash)
145
- end
146
- end
147
-
148
- # Initializes the instance from a given +hash+.
149
- def initialize_from_hash(hash)
150
- @hash = hash
151
- shadow_core_methods if @hash.kind_of?(Hash)
152
- end
153
-
154
- # Dynamically defines methods from the Array of +@@core_methods_to_shadow+
155
- # to "shadow" inherited methods. Returns a value from the response Hash in
156
- # case a matching public method and a key from the Hash could be found.
157
- def shadow_core_methods
158
- @@core_methods_to_shadow.each do |method|
159
- if self.public_methods.include?(method.to_s) && value_from_hash(method)
160
- self.class.send(:define_method, method) { value_from_hash(method) }
161
- end
162
- end
163
- end
164
-
165
- # Returns a value from the response Hash. Tries to convert the given +key+
166
- # into a Symbol or a String to find the value to return.
167
- def value_from_hash(key)
168
- return nil unless @hash
169
- @hash[key.to_sym] || @hash[key.to_s]
170
- end
171
- end
172
-
173
- end
@@ -1,127 +0,0 @@
1
- class WsdlFactory
2
- attr_accessor :namespace_uri, :service_methods, :choice_elements
3
-
4
- def initialize(new_options = {})
5
- options = {
6
- :namespace_uri => "http://some.example.com",
7
- :service_methods => {"findById" => ["id"]},
8
- :choice_elements => {}
9
- }.update(new_options)
10
-
11
- @namespace_uri = options[:namespace_uri]
12
- @service_methods = options[:service_methods]
13
- @choice_elements = options[:choice_elements]
14
- end
15
-
16
- def build
17
- wsdl = '<wsdl:definitions name="SomeService" targetNamespace="' << namespace_uri << '"
18
- xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://example.com"
19
- xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
20
- <wsdl:types>
21
- <xs:schema attributeFormDefault="unqualified" elementFormDefault="unqualified"
22
- targetNamespace="http://example.com" xmlns:tns="http://example.com"
23
- xmlns:xs="http://www.w3.org/2001/XMLSchema">'
24
- wsdl << build_elements
25
- wsdl << '<xs:element name="result" type="tns:result" />'
26
- wsdl << build_complex_types
27
- wsdl << '<xs:complexType name="result">
28
- <xs:sequence><xs:element name="token" type="xs:token" /></xs:sequence>
29
- </xs:complexType>
30
- </xs:schema>
31
- </wsdl:types>'
32
- wsdl << build_messages
33
- wsdl << '<wsdl:portType name="SomeWebService">'
34
- wsdl << build_operation_input_output
35
- wsdl << '</wsdl:portType>
36
- <wsdl:binding name="SomeServiceSoapBinding" type="tns:SomeService">
37
- <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />'
38
- wsdl << build_operation_input_output_body
39
- wsdl << '</wsdl:binding>
40
- <wsdl:service name="SomeService">
41
- <wsdl:port binding="tns:SomeServiceSoapBinding" name="SomeServicePort">
42
- <soap:address location="http://example.com/SomeService" />
43
- </wsdl:port>
44
- </wsdl:service>
45
- </wsdl:definitions>'
46
- end
47
-
48
- def build_elements
49
- wsdl = service_methods.keys.map { |method|
50
- '<xs:element name="' << method << '" type="tns:' << method << '" />
51
- <xs:element name="' << method << 'Response" type="tns:' << method << 'Response" />'
52
- }.to_s
53
- wsdl << choice_elements.map { |c_method, c_elements|
54
- c_elements.map { |c_element|
55
- '<xs:element name="' << c_element << '" type="tns:' << c_element << 'Value" />'
56
- }.to_s
57
- }.to_s
58
- wsdl
59
- end
60
-
61
- def build_complex_types
62
- service_methods.map { |method, inputs|
63
- wsdl = '<xs:complexType name="' << method << '"><xs:sequence>'
64
- inputs.each do |input|
65
- if choice_elements.keys.include? input
66
- wsdl << '<xs:choice>'
67
- wsdl << choice_elements[input].map { |element|
68
- '<xs:element ref="tns:' << element << '"/>'
69
- }.to_s
70
- wsdl << '</xs:choice>'
71
- else
72
- wsdl << '<xs:element minOccurs="0" name="' << input << '" type="xs:string" />'
73
- end
74
- end
75
- wsdl << '</xs:sequence></xs:complexType>'
76
- wsdl << build_complex_types_choice_elements
77
- wsdl << '<xs:complexType name="' << method << 'Response"><xs:sequence>
78
- <xs:element minOccurs="0" name="return" type="tns:result" />
79
- </xs:sequence></xs:complexType>'
80
- }.to_s
81
- end
82
-
83
- def build_complex_types_choice_elements
84
- choice_elements.map { |c_method, c_elements|
85
- c_elements.map { |c_element|
86
- '<xs:complexType name="' << c_element << 'Value"><xs:sequence>
87
- <xs:element minOccurs="0" name="' << c_element << '" type="xs:string" />
88
- </xs:sequence></xs:complexType>'
89
- }.to_s
90
- }.to_s
91
- end
92
-
93
- def build_messages
94
- service_methods.keys.map { |method|
95
- '<wsdl:message name="' << method << '">
96
- <wsdl:part element="tns:' << method << '" name="parameters"> </wsdl:part>
97
- </wsdl:message>
98
- <wsdl:message name="' << method << 'Response">
99
- <wsdl:part element="tns:' << method << 'Response" name="parameters"> </wsdl:part>
100
- </wsdl:message>'
101
- }.to_s
102
- end
103
-
104
- def build_operation_input_output
105
- service_methods.keys.map { |method|
106
- '<wsdl:operation name="' << method << '">
107
- <wsdl:input message="tns:' << method << '" name="' << method << '"> </wsdl:input>
108
- <wsdl:output message="tns:' << method << 'Response" name="' << method << 'Response"> </wsdl:output>
109
- </wsdl:operation>'
110
- }.to_s
111
- end
112
-
113
- def build_operation_input_output_body
114
- service_methods.keys.map { |method|
115
- '<wsdl:operation name="' << method << '">
116
- <soap:operation soapAction="" style="document" />
117
- <wsdl:input name="' << method << '">
118
- <soap:body use="literal" />
119
- </wsdl:input>
120
- <wsdl:output name="' << method << 'Response">
121
- <soap:body use="literal" />
122
- </wsdl:output>
123
- </wsdl:operation>'
124
- }.to_s
125
- end
126
-
127
- end
@@ -1,75 +0,0 @@
1
- module SoapResponseFixture
2
-
3
- def some_response_hash
4
- {
5
- :authentication => {
6
- :user => "example",
7
- :password => "secret"
8
- },
9
- :success => true,
10
- :tokens => ["abc", "xyz", "123"]
11
- }
12
- end
13
-
14
- def response_hash_with_id
15
- some_response_hash.dup.update :id => "shadow_id"
16
- end
17
-
18
- def response_hash_with_inspect
19
- some_response_hash.dup.update :inspect => "shadow_inspect"
20
- end
21
-
22
- def some_soap_response
23
- build_soap_response
24
- end
25
-
26
- def soap_response_with_id
27
- build_soap_response '<id>shadow_id</id>'
28
- end
29
-
30
- def soap_response_with_inspect
31
- build_soap_response '<inspect>shadow_inspect</inspect>'
32
- end
33
-
34
- def soap_fault_response
35
- '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">' <<
36
- '<soap:Body>' <<
37
- '<soap:Fault>' <<
38
- '<faultcode>' << soap_fault_code << '</faultcode>' <<
39
- '<faultstring>' << soap_fault_message << '</faultstring>' <<
40
- '</soap:Fault>' <<
41
- '</soap:Body>' <<
42
- '</soap:Envelope>'
43
- end
44
-
45
- def soap_fault_message
46
- "Failed to authenticate client."
47
- end
48
-
49
- def soap_fault_code
50
- "soap:Server"
51
- end
52
-
53
- private
54
-
55
- def build_soap_response(mixin = "")
56
- '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">' <<
57
- '<soap:Body>' <<
58
- '<ns2:result xmlns:ns2="http://example.com/">' <<
59
- '<return>' <<
60
- '<authentication>' <<
61
- '<user>example</user>' <<
62
- '<password>secret</password>' <<
63
- '</authentication>' <<
64
- mixin <<
65
- '<success>true</success>' <<
66
- '<tokens>abc</tokens>' <<
67
- '<tokens>xyz</tokens>' <<
68
- '<tokens>123</tokens>' <<
69
- '</return>' <<
70
- '</ns2:result>' <<
71
- '</soap:Body>' <<
72
- '</soap:Envelope>'
73
- end
74
-
75
- end
data/test/helper.rb DELETED
@@ -1,48 +0,0 @@
1
- require "rubygems"
2
- require "test/unit"
3
- require "mocha"
4
- require "shoulda"
5
- require "apricoteatsgorilla"
6
-
7
- require File.join(File.dirname(__FILE__), "..", "lib", "savon")
8
- require File.join(File.dirname(__FILE__), "factories", "wsdl")
9
- require File.join(File.dirname(__FILE__), "fixtures", "soap_response_fixture")
10
-
11
- module TestHelper
12
-
13
- def some_url
14
- "http://example.com"
15
- end
16
-
17
- def some_uri
18
- URI(some_url)
19
- end
20
-
21
- def service_http_mock(response_body)
22
- http_mock = mock("Net::HTTP")
23
- http_mock.stubs(:get).returns(response_mock(WsdlFactory.new.build))
24
- http_mock.stubs(:request_post).returns(response_mock(response_body))
25
- http_mock
26
- end
27
-
28
- def http_mock(response_body)
29
- http_mock = mock("Net::HTTP")
30
- http_mock.stubs(:get).returns(response_mock(response_body))
31
- http_mock
32
- end
33
-
34
- def response_mock(response_body)
35
- build_response_mock("200", "OK", response_body)
36
- end
37
-
38
- def response_error_mock
39
- build_response_mock("404", "NotFound")
40
- end
41
-
42
- def build_response_mock(code, message, body = nil)
43
- response_mock = mock("Net::HTTPResponse")
44
- response_mock.stubs(:code => code, :message => message, :body => body)
45
- response_mock
46
- end
47
-
48
- end
@@ -1,191 +0,0 @@
1
- require File.join(File.dirname(__FILE__), "..", "helper")
2
-
3
- class TestSavonResponse < Test::Unit::TestCase
4
-
5
- include TestHelper
6
- include SoapResponseFixture
7
-
8
- context "A Savon::Response instance" do
9
- setup do
10
- ApricotEatsGorilla.sort_keys = true
11
- Savon::Response.core_methods_to_shadow = [:id] # set to default
12
- end
13
-
14
- context "initialized with a Net::HTTPResponse containing a successful SOAP response" do
15
- setup { @response = Savon::Response.new response_mock(some_soap_response) }
16
-
17
- should "return that the request was successful" do
18
- assert_equal true, @response.success?
19
- assert_equal false, @response.error?
20
- end
21
-
22
- should "return nil for error_code and error_message" do
23
- assert_nil @response.error_code
24
- assert_nil @response.error_message
25
- end
26
-
27
- should "return the SOAP response XML when calling to_s" do
28
- assert_equal some_soap_response, @response.to_s
29
- end
30
-
31
- should "return the Hash translated from the SOAP response XML when calling to_hash" do
32
- assert_kind_of Hash, @response.to_hash
33
- assert_equal some_response_hash, @response.to_hash
34
- end
35
-
36
- should "return a Hash for Hash values accessed through []" do
37
- assert_kind_of Hash, @response[:authentication]
38
- assert_equal some_response_hash[:authentication], @response[:authentication]
39
- end
40
-
41
- should "return the actual value for values other than Hashes through []" do
42
- assert_kind_of TrueClass, @response[:success]
43
- assert_kind_of Array, @response[:tokens]
44
- assert_equal some_response_hash[:success], @response[:success]
45
- assert_equal some_response_hash[:tokens], @response[:tokens]
46
- end
47
-
48
- should "return nil when trying to access a not-existing key from the Hash" do
49
- assert_nil @response.some_undefined_key
50
- end
51
-
52
- should "return a Savon::Response for Hash values accessed through method_missing" do
53
- assert_kind_of Savon::Response, @response.authentication
54
- end
55
-
56
- should "return the actual value for values other than Hashes through method_missing" do
57
- assert_kind_of TrueClass, @response.success
58
- assert_kind_of Array, @response.tokens
59
- assert_equal some_response_hash[:success], @response.success
60
- assert_equal some_response_hash[:tokens], @response.tokens
61
- end
62
-
63
- should "by default shadow the :id method if it was found in the Hash" do
64
- response_with_id = Savon::Response.new response_mock(soap_response_with_id)
65
- assert_equal response_hash_with_id[:id], response_with_id.id
66
- end
67
-
68
- should "shadow user-specified core methods in case they were found in the Hash" do
69
- Savon::Response.core_methods_to_shadow = [:inspect]
70
- response_with_inspect = Savon::Response.new response_mock(soap_response_with_inspect)
71
-
72
- assert_equal response_hash_with_inspect[:inspect], response_with_inspect.inspect
73
- end
74
- end
75
-
76
- context "initialized with a Hash" do
77
- setup { @response = Savon::Response.new some_response_hash }
78
-
79
- should "return nil for HTTP::Response-specific methods" do
80
- assert_nil @response.success?
81
- assert_nil @response.error?
82
- assert_nil @response.error_code
83
- assert_nil @response.error_message
84
- assert_nil @response.to_s
85
- end
86
-
87
- should "return the given Hash when calling to_hash" do
88
- assert_kind_of Hash, @response.to_hash
89
- assert_equal some_response_hash, @response.to_hash
90
- end
91
-
92
- should "return a Hash for Hash values accessed through []" do
93
- assert_kind_of Hash, @response[:authentication]
94
- assert_equal some_response_hash[:authentication], @response[:authentication]
95
- end
96
-
97
- should "return the actual value for values other than Hashes through []" do
98
- assert_kind_of TrueClass, @response[:success]
99
- assert_kind_of Array, @response[:tokens]
100
- assert_equal some_response_hash[:success], @response[:success]
101
- assert_equal some_response_hash[:tokens], @response[:tokens]
102
- end
103
-
104
- should "return a Savon::Response for Hash values accessed through method_missing" do
105
- assert_kind_of Savon::Response, @response.authentication
106
- end
107
-
108
- should "return the actual value for values other than Hashes through method_missing" do
109
- assert_kind_of TrueClass, @response.success
110
- assert_kind_of Array, @response.tokens
111
- assert_equal some_response_hash[:success], @response.success
112
- assert_equal some_response_hash[:tokens], @response.tokens
113
- end
114
-
115
- should "by default shadow the :id method if it was found in the Hash" do
116
- hash_with_id = response_hash_with_id
117
- @response = Savon::Response.new hash_with_id
118
- assert_equal hash_with_id[:id], @response.id
119
- end
120
-
121
- should "shadow user-specified core methods in case they were found in the Hash" do
122
- Savon::Response.core_methods_to_shadow = [:inspect]
123
- response_with_inspect = Savon::Response.new response_hash_with_inspect
124
-
125
- assert_equal response_hash_with_inspect[:inspect], response_with_inspect.inspect
126
- end
127
- end
128
-
129
- context "initialized with a Net::HTTPResponse containing a SOAP fault" do
130
- setup { @response = Savon::Response.new response_mock(soap_fault_response) }
131
-
132
- should "return that the request was not successful" do
133
- assert_equal false, @response.success?
134
- assert_equal true, @response.error?
135
- end
136
-
137
- should "return the error_code and error_message" do
138
- assert_equal soap_fault_code, @response.error_code
139
- assert_equal soap_fault_message, @response.error_message
140
- end
141
-
142
- should "return the SOAP response XML when calling to_s" do
143
- assert_equal soap_fault_response, @response.to_s
144
- end
145
-
146
- should "return nil when calling to_hash" do
147
- assert_nil @response.to_hash
148
- end
149
-
150
- should "return nil when trying to access Hash values through []" do
151
- assert_nil @response[:some_key]
152
- end
153
-
154
- should "return nil when trying to access Hash values through method_missing" do
155
- assert_nil @response.some_key
156
- end
157
- end
158
-
159
- context "initialized with a Net::HTTPResponse error" do
160
- setup { @response = Savon::Response.new response_error_mock }
161
-
162
- should "return that the request was not successful" do
163
- assert_equal false, @response.success?
164
- assert_equal true, @response.error?
165
- end
166
-
167
- should "return the error_code and error_message" do
168
- assert_equal "404", @response.error_code
169
- assert_equal "NotFound", @response.error_message
170
- end
171
-
172
- should "return nil when calling to_s" do
173
- assert_nil @response.to_s
174
- end
175
-
176
- should "return nil when calling to_hash" do
177
- assert_nil @response.to_hash
178
- end
179
-
180
- should "return nil when trying to access Hash values through []" do
181
- assert_nil @response[:some_key]
182
- end
183
-
184
- should "return nil when trying to access Hash values through method_missing" do
185
- assert_nil @response.some_key
186
- end
187
- end
188
-
189
- end
190
-
191
- end