google4r-checkout 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +40 -0
- data/LICENSE +22 -0
- data/README +76 -0
- data/lib/google4r/checkout.rb +33 -0
- data/lib/google4r/checkout/commands.rb +260 -0
- data/lib/google4r/checkout/frontend.rb +108 -0
- data/lib/google4r/checkout/notifications.rb +549 -0
- data/lib/google4r/checkout/shared.rb +541 -0
- data/lib/google4r/checkout/xml_generation.rb +313 -0
- data/test/integration/checkout_command_test.rb +103 -0
- data/test/unit/address_test.rb +131 -0
- data/test/unit/area_test.rb +44 -0
- data/test/unit/checkout_command_test.rb +116 -0
- data/test/unit/checkout_command_xml_generator_test.rb +203 -0
- data/test/unit/command_test.rb +115 -0
- data/test/unit/flat_rate_shipping_test.rb +114 -0
- data/test/unit/frontend_test.rb +63 -0
- data/test/unit/item_test.rb +159 -0
- data/test/unit/marketing_preferences_test.rb +65 -0
- data/test/unit/merchant_code_test.rb +122 -0
- data/test/unit/new_order_notification_test.rb +115 -0
- data/test/unit/notification_acknowledgement_test.rb +43 -0
- data/test/unit/notification_handler_test.rb +93 -0
- data/test/unit/order_adjustment_test.rb +119 -0
- data/test/unit/order_state_change_notification_test.rb +159 -0
- data/test/unit/pickup_shipping_test.rb +70 -0
- data/test/unit/postal_area_test.rb +71 -0
- data/test/unit/private_data_parser_test.rb +68 -0
- data/test/unit/shipping_adjustment_test.rb +100 -0
- data/test/unit/shipping_method_test.rb +41 -0
- data/test/unit/shopping_cart_test.rb +146 -0
- data/test/unit/tax_rule_test.rb +70 -0
- data/test/unit/tax_table_test.rb +82 -0
- data/test/unit/us_country_area_test.rb +76 -0
- data/test/unit/us_state_area_test.rb +70 -0
- data/test/unit/us_zip_area_test.rb +66 -0
- data/test/unit/world_area_test.rb +48 -0
- data/var/cacert.pem +7815 -0
- metadata +92 -0
@@ -0,0 +1,313 @@
|
|
1
|
+
#--
|
2
|
+
# Project: google4r
|
3
|
+
# File: lib/google4r/checkout/xml_generation.rb
|
4
|
+
# Author: Manuel Holtgrewe <purestorm at ggnore dot net>
|
5
|
+
# Copyright: (c) 2007 by Manuel Holtgrewe
|
6
|
+
# License: MIT License as follows:
|
7
|
+
#
|
8
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
9
|
+
# a copy of this software and associated documentation files (the
|
10
|
+
# "Software"), to deal in the Software without restriction, including
|
11
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
12
|
+
# distribute, sublicense, and/or sell copies of the Software, and to permit
|
13
|
+
# persons to whom the Software is furnished to do so, subject to the
|
14
|
+
# following conditions:
|
15
|
+
#
|
16
|
+
# The above copyright notice and this permission notice shall be included
|
17
|
+
# in all copies or substantial portions of the Software.
|
18
|
+
#
|
19
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
20
|
+
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
21
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
22
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
23
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
24
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
25
|
+
# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
26
|
+
#++
|
27
|
+
# This file contains the classes that allow to persist the object hierarchies
|
28
|
+
# that are created with the Google Checkout API to XML.
|
29
|
+
|
30
|
+
require 'stringio'
|
31
|
+
require 'rexml/document'
|
32
|
+
|
33
|
+
module Google4R #:nodoc:
|
34
|
+
module Checkout #:nodoc:
|
35
|
+
# Use the CheckoutXmlGenerator to create an XML document from a CheckoutCommand
|
36
|
+
# object.
|
37
|
+
#
|
38
|
+
# Usage:
|
39
|
+
#
|
40
|
+
# checkout = CheckoutCommand.new
|
41
|
+
# # set up the CheckoutCommand
|
42
|
+
#
|
43
|
+
# generator = CheckoutCommandXmlGenerator.new(checkout)
|
44
|
+
# puts generator.generate # => "<xml? version=..."
|
45
|
+
# File.new('some.xml', 'w') { |f| f.write generator.generate }
|
46
|
+
#--
|
47
|
+
# TODO: Refactor the big, monolitic generator into smaller, easier testable ones. One for each major part of the resulting XML document. This will also reduce the overhead in generating other types of XML documents.
|
48
|
+
#++
|
49
|
+
class CheckoutCommandXmlGenerator
|
50
|
+
# Initializes the CheckoutCommandXmlGenerator with the CheckoutCommand it is
|
51
|
+
# to conver to XML.
|
52
|
+
def initialize(checkout_command)
|
53
|
+
@checkout_command = checkout_command
|
54
|
+
end
|
55
|
+
|
56
|
+
# Creates an XML document from the checkout_command passed into the constructor. Returns
|
57
|
+
# the resulting XML string.
|
58
|
+
def generate
|
59
|
+
@document = REXML::Document.new
|
60
|
+
|
61
|
+
declaration = REXML::XMLDecl.new
|
62
|
+
declaration.encoding = 'utf-8'
|
63
|
+
@document << declaration
|
64
|
+
|
65
|
+
self.process_checkout_command(@checkout_command)
|
66
|
+
|
67
|
+
io = StringIO.new
|
68
|
+
@document.write(io, 0) # TODO: Maybe replace 0 by -1 so no spaces are inserted?
|
69
|
+
return io.string
|
70
|
+
end
|
71
|
+
|
72
|
+
protected
|
73
|
+
|
74
|
+
def process_checkout_command(command)
|
75
|
+
root = @document.add_element('checkout-shopping-cart', { 'xmlns' => 'http://checkout.google.com/schema/2' })
|
76
|
+
|
77
|
+
self.process_shopping_shopping_cart(root, command.shopping_cart)
|
78
|
+
|
79
|
+
# <merchant-checkout-flow-support>
|
80
|
+
flow_element = root.add_element('checkout-flow-support').add_element('merchant-checkout-flow-support')
|
81
|
+
|
82
|
+
# <tax-tables>
|
83
|
+
if command.tax_tables then
|
84
|
+
self.process_tax_tables(command.tax_tables, flow_element)
|
85
|
+
end
|
86
|
+
|
87
|
+
# <continue-shopping-url>
|
88
|
+
if not command.continue_shopping_url.nil? then
|
89
|
+
flow_element.add_element('continue-shopping-url').text = command.continue_shopping_url
|
90
|
+
end
|
91
|
+
|
92
|
+
# <edit-cart-url>
|
93
|
+
if not command.edit_cart_url.nil? then
|
94
|
+
flow_element.add_element('edit-cart-url').text = command.edit_cart_url
|
95
|
+
end
|
96
|
+
|
97
|
+
# <request-buyer-phone-number>
|
98
|
+
if not command.request_buyer_phone_number.nil? then
|
99
|
+
flow_element.add_element('request-buyer-phone-number').text =
|
100
|
+
if command.request_buyer_phone_number then
|
101
|
+
"true"
|
102
|
+
else
|
103
|
+
"false"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# <shipping-methods>
|
108
|
+
shippings_element = flow_element.add_element('shipping-methods')
|
109
|
+
command.shipping_methods.each do |shipping_method|
|
110
|
+
self.process_shipping_method(shippings_element, shipping_method)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# adds the tax-tables to the parent xml element
|
115
|
+
# assumes that the first member of the tax_tables array is the default tax rule table
|
116
|
+
# and that all others are alternate tax rules
|
117
|
+
def process_tax_tables(tax_tables, parent)
|
118
|
+
tax_tables_element = parent.add_element('tax-tables')
|
119
|
+
|
120
|
+
# assumes that the first tax table is the default
|
121
|
+
default_table = tax_tables.first
|
122
|
+
|
123
|
+
default_table_element = tax_tables_element.add_element('default-tax-table')
|
124
|
+
rules_element = default_table_element.add_element('tax-rules')
|
125
|
+
|
126
|
+
default_table.rules.each do |rule|
|
127
|
+
default_rule_element = rules_element.add_element('default-tax-rule')
|
128
|
+
default_rule_element.add_element('shipping-taxed').text=rule.shipping_taxed.to_s
|
129
|
+
default_rule_element.add_element('rate').text=rule.rate.to_s
|
130
|
+
self.process_area(default_rule_element.add_element('tax-area'), rule.area)
|
131
|
+
end
|
132
|
+
|
133
|
+
# populate alternate tax tables
|
134
|
+
alt_tables = tax_tables.last(tax_tables.length-1)
|
135
|
+
alt_tables_element = tax_tables_element.add_element('alternate-tax-tables')
|
136
|
+
|
137
|
+
alt_tables.each do |table|
|
138
|
+
table_element = alt_tables_element.add_element('alternate-tax-table')
|
139
|
+
table_element.add_attribute('name', table.name)
|
140
|
+
table_element.add_attribute('standalone', table.standalone.to_s)
|
141
|
+
|
142
|
+
rules_element = table_element.add_element('alternate-tax-rules')
|
143
|
+
table.rules.each do |rule|
|
144
|
+
alt_rule_element = rules_element.add_element('alternate-tax-rule')
|
145
|
+
alt_rule_element.add_element('rate').text=rule.rate.to_s
|
146
|
+
|
147
|
+
self.process_area(alt_rule_element.add_element('tax-area'), rule.area)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
def process_shopping_shopping_cart(parent, shopping_cart)
|
154
|
+
cart_element = parent.add_element('shopping-cart')
|
155
|
+
|
156
|
+
# add <cart-expiration> tag to the cart if a time has been added to the cart
|
157
|
+
if not shopping_cart.expires_at.nil? then
|
158
|
+
cart_element.add_element('cart-expiration').add_element('good-until-date').text =
|
159
|
+
shopping_cart.expires_at.iso8601
|
160
|
+
end
|
161
|
+
|
162
|
+
# add <merchant-private-data> to the cart if any has been set
|
163
|
+
if not shopping_cart.private_data.nil? then
|
164
|
+
self.process_hash(cart_element.add_element('merchant-private-data'), shopping_cart.private_data)
|
165
|
+
end
|
166
|
+
|
167
|
+
# process the items in the cart
|
168
|
+
items_element = cart_element.add_element('items')
|
169
|
+
shopping_cart.items.each do |item|
|
170
|
+
self.process_item(items_element, item)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# Adds an <item> tag to the tag parent with the appropriate values.
|
175
|
+
def process_item(parent, item)
|
176
|
+
item_element = parent.add_element('item')
|
177
|
+
|
178
|
+
item_element.add_element('item-name').text = item.name
|
179
|
+
item_element.add_element('item-description').text = item.description
|
180
|
+
|
181
|
+
item_element.add_element('unit-price', { 'currency' => item.unit_price.currency }).text = item.unit_price.to_s
|
182
|
+
item_element.add_element('quantity').text = item.quantity.to_i
|
183
|
+
|
184
|
+
if not item.id.nil? then
|
185
|
+
item_element.add_element('merchant-item-id').text = item.id
|
186
|
+
end
|
187
|
+
|
188
|
+
if not item.private_data.nil? then
|
189
|
+
self.process_hash(item_element.add_element('merchant-private-item-data'), item.private_data)
|
190
|
+
end
|
191
|
+
|
192
|
+
# The above was easy; now we need to get the appropriate tax table for this
|
193
|
+
# item. The Item class makes sure that the table exists.
|
194
|
+
if not item.tax_table.nil? then
|
195
|
+
item_element.add_element('tax-table-selector').text = item.tax_table.name
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# Adds an item for the given shipping method.
|
200
|
+
def process_shipping_method(parent, shipping_method)
|
201
|
+
if shipping_method.kind_of? PickupShipping then
|
202
|
+
process_pickup_shipping(parent, shipping_method)
|
203
|
+
elsif shipping_method.kind_of? FlatRateShipping then
|
204
|
+
process_flat_rate_shipping(parent, shipping_method)
|
205
|
+
else
|
206
|
+
raise "Unknown ShippingMethod type of #{shipping_method.inspect}!"
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def process_flat_rate_shipping(parent, shipping)
|
211
|
+
element = parent.add_element('flat-rate-shipping')
|
212
|
+
element.add_attribute('name', shipping.name)
|
213
|
+
element.add_element('price', { 'currency' => shipping.price.currency }).text = shipping.price.to_s
|
214
|
+
|
215
|
+
if shipping.excluded_areas.length + shipping.allowed_areas.length > 0 then
|
216
|
+
restrictions_tag = element.add_element('shipping-restrictions')
|
217
|
+
|
218
|
+
if shipping.allowed_areas.length > 0 then
|
219
|
+
allowed_tag = restrictions_tag.add_element('allowed-areas')
|
220
|
+
|
221
|
+
shipping.allowed_areas.each do |area|
|
222
|
+
self.process_area(allowed_tag, area)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
if shipping.excluded_areas.length > 0 then
|
227
|
+
excluded_tag = restrictions_tag.add_element('excluded-areas')
|
228
|
+
|
229
|
+
shipping.excluded_areas.each do |area|
|
230
|
+
self.process_area(excluded_tag, area)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def process_pickup_shipping(parent, shipping)
|
237
|
+
element = parent.add_element('pickup')
|
238
|
+
element.add_attribute('name', shipping.name)
|
239
|
+
element.add_element('price', { 'currency' => shipping.price.currency }).text = shipping.price.to_s
|
240
|
+
end
|
241
|
+
|
242
|
+
# Adds an appropriate tag for the given Area subclass instance to the parent Element.
|
243
|
+
def process_area(parent, area)
|
244
|
+
if area.kind_of? UsZipArea then
|
245
|
+
parent.add_element('us-zip-area').add_element('zip-pattern').text = area.pattern
|
246
|
+
elsif area.kind_of? UsCountryArea then
|
247
|
+
parent.add_element('us-country-area', { 'country-area' => area.area })
|
248
|
+
elsif area.kind_of? UsStateArea then
|
249
|
+
parent.add_element('us-state-area').add_element('state').text = area.state
|
250
|
+
elsif area.kind_of? WorldArea then
|
251
|
+
parent.add_element('world-area')
|
252
|
+
elsif area.kind_of? PostalArea then
|
253
|
+
postal_area_element = parent.add_element('postal-area')
|
254
|
+
postal_area_element.add_element('country-code').text = area.country_code
|
255
|
+
postal_area_element.add_element('postal-code-pattern').text = area.postal_code_pattern
|
256
|
+
else
|
257
|
+
raise "Area of unknown type: #{area.inspect}."
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
# Converts a Hash into an XML structure. The keys are converted to tag names. If
|
262
|
+
# the values are Hashs themselves then process_hash is called upon them. If the
|
263
|
+
# values are Arrays then a new element with the key's name will be created.
|
264
|
+
#
|
265
|
+
# If a value is an Array then this array will be flattened before it is processed.
|
266
|
+
# Thus, nested arrays are not allowed.
|
267
|
+
#
|
268
|
+
# === Example
|
269
|
+
#
|
270
|
+
# process_hash(parent, { 'foo' => { 'bar' => 'baz' } })
|
271
|
+
#
|
272
|
+
# # will produce a structure that is equivalent to.
|
273
|
+
#
|
274
|
+
# <foo>
|
275
|
+
# <bar>baz</bar>
|
276
|
+
# </foo>
|
277
|
+
#
|
278
|
+
#
|
279
|
+
# process_hash(parent, { 'foo' => [ { 'bar' => 'baz' }, "d'oh", 2 ] })
|
280
|
+
#
|
281
|
+
# # will produce a structure that is equivalent to.
|
282
|
+
#
|
283
|
+
# <foo>
|
284
|
+
# <bar>baz</bar>
|
285
|
+
# </foo>
|
286
|
+
# <foo>d&</foo>
|
287
|
+
# <foo>2</foo>
|
288
|
+
def process_hash(parent, hash)
|
289
|
+
hash.each do |key, value|
|
290
|
+
if value.kind_of? Array then
|
291
|
+
value.flatten.each do |arr_entry|
|
292
|
+
if arr_entry.kind_of? Hash then
|
293
|
+
self.process_hash(parent.add_element(self.str2tag_name(key.to_s)), arr_entry)
|
294
|
+
else
|
295
|
+
parent.add_element(self.str2tag_name(key.to_s)).text = arr_entry.to_s
|
296
|
+
end
|
297
|
+
end
|
298
|
+
elsif value.kind_of? Hash then
|
299
|
+
process_hash(parent.add_element(self.str2tag_name(key.to_s)), value)
|
300
|
+
else
|
301
|
+
parent.add_element(self.str2tag_name(key.to_s)).text = value.to_s
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
# Converts a string to a valid XML tag name. Whitespace will be converted into a dash/minus
|
307
|
+
# sign, non alphanumeric characters that are neither "-" nor "_" nor ":" will be stripped.
|
308
|
+
def str2tag_name(str)
|
309
|
+
str.gsub(%r{\s}, '-').gsub(%r{[^a-zA-Z0-9\-\_:]}, '')
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
#--
|
2
|
+
# Project: google_checkout4r
|
3
|
+
# File: test/checkout/integration/checkout_command.rb
|
4
|
+
# Author: Manuel Holtgrewe <purestorm at ggnore dot net>
|
5
|
+
# Copyright: (c) 2007 by Manuel Holtgrewe
|
6
|
+
# License: MIT License as follows:
|
7
|
+
#
|
8
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
9
|
+
# a copy of this software and associated documentation files (the
|
10
|
+
# "Software"), to deal in the Software without restriction, including
|
11
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
12
|
+
# distribute, sublicense, and/or sell copies of the Software, and to permit
|
13
|
+
# persons to whom the Software is furnished to do so, subject to the
|
14
|
+
# following conditions:
|
15
|
+
#
|
16
|
+
# The above copyright notice and this permission notice shall be included
|
17
|
+
# in all copies or substantial portions of the Software.
|
18
|
+
#
|
19
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
20
|
+
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
21
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
22
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
23
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
24
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
25
|
+
# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
26
|
+
#++
|
27
|
+
|
28
|
+
require File.expand_path(File.dirname(__FILE__)) + '/../test_helper'
|
29
|
+
|
30
|
+
require 'google4r/checkout'
|
31
|
+
|
32
|
+
require 'test/frontend_configuration'
|
33
|
+
|
34
|
+
# Integration tests for the CheckoutCommand class.
|
35
|
+
#
|
36
|
+
# Tests the CheckoutCommand class against the Google Checkout Web Service.
|
37
|
+
class Google4R::Checkout::CheckoutCommandIntegrationTest < Test::Unit::TestCase
|
38
|
+
include Google4R::Checkout
|
39
|
+
|
40
|
+
def setup
|
41
|
+
@frontend = Frontend.new(FRONTEND_CONFIGURATION)
|
42
|
+
@frontend.tax_table_factory = TestTaxTableFactory.new
|
43
|
+
@command = @frontend.create_checkout_command
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_sending_to_google_works_with_valid_request
|
47
|
+
setup_command(@command)
|
48
|
+
result = @command.send_to_google_checkout
|
49
|
+
assert_kind_of CheckoutRedirectResponse, result
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_using_invalid_credentials_raise_google_checkout_error
|
53
|
+
invalid_patches = [ [ :merchant_id, 'invalid' ], [ :merchant_key, 'invalid' ] ]
|
54
|
+
|
55
|
+
invalid_patches.each do |patch|
|
56
|
+
config = FRONTEND_CONFIGURATION.dup
|
57
|
+
config[patch[0]] = patch[1]
|
58
|
+
@frontend = Frontend.new(config)
|
59
|
+
@frontend.tax_table_factory = TestTaxTableFactory.new
|
60
|
+
@command = @frontend.create_checkout_command
|
61
|
+
|
62
|
+
setup_command(@command)
|
63
|
+
assert_raises(GoogleCheckoutError) { @command.send_to_google_checkout }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_invalid_xml_raises_google_checkout_error
|
68
|
+
class << @command
|
69
|
+
def to_xml
|
70
|
+
''
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
setup_command(@command)
|
75
|
+
assert_raises(GoogleCheckoutError) { @command.send_to_google_checkout }
|
76
|
+
end
|
77
|
+
|
78
|
+
protected
|
79
|
+
|
80
|
+
# Sets up the given CheckoutCommand so it contains some
|
81
|
+
# shipping methods and its cart contains some items.
|
82
|
+
def setup_command(command)
|
83
|
+
# Add shipping methods.
|
84
|
+
command.create_shipping_method(FlatRateShipping) do |shipping|
|
85
|
+
shipping.name = 'UPS Ground Shipping'
|
86
|
+
shipping.price = Money.new(2000) # USD 20, GPB 20, etc.
|
87
|
+
shipping.create_allowed_area(UsCountryArea) do |area|
|
88
|
+
area.area = UsCountryArea::ALL
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Add items to the cart.
|
93
|
+
1.upto(5) do |i|
|
94
|
+
command.shopping_cart.create_item do |item|
|
95
|
+
item.name = "Test Item #{i}"
|
96
|
+
item.description = "This is a test item (#{i})"
|
97
|
+
item.unit_price = Money.new(350)
|
98
|
+
item.quantity = i * 3
|
99
|
+
item.id = "test-#{i}-123456789"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
#--
|
2
|
+
# Project: google_checkout4r
|
3
|
+
# File: test/unit/address_test.rb
|
4
|
+
# Author: Manuel Holtgrewe <purestorm at ggnore dot net>
|
5
|
+
# Copyright: (c) 2007 by Manuel Holtgrewe
|
6
|
+
# License: MIT License as follows:
|
7
|
+
#
|
8
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
9
|
+
# a copy of this software and associated documentation files (the
|
10
|
+
# "Software"), to deal in the Software without restriction, including
|
11
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
12
|
+
# distribute, sublicense, and/or sell copies of the Software, and to permit
|
13
|
+
# persons to whom the Software is furnished to do so, subject to the
|
14
|
+
# following conditions:
|
15
|
+
#
|
16
|
+
# The above copyright notice and this permission notice shall be included
|
17
|
+
# in all copies or substantial portions of the Software.
|
18
|
+
#
|
19
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
20
|
+
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
21
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
22
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
23
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
24
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
25
|
+
# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
26
|
+
#++
|
27
|
+
|
28
|
+
require File.expand_path(File.dirname(__FILE__)) + '/../test_helper'
|
29
|
+
|
30
|
+
require 'google4r/checkout'
|
31
|
+
|
32
|
+
require 'test/frontend_configuration'
|
33
|
+
|
34
|
+
# Test for the class Address.
|
35
|
+
class Google4R::Checkout::AddressTest < Test::Unit::TestCase
|
36
|
+
include Google4R::Checkout
|
37
|
+
|
38
|
+
def setup
|
39
|
+
@data =
|
40
|
+
{
|
41
|
+
:contact_name => 'John Smith',
|
42
|
+
:email => 'johnsmith@example.com',
|
43
|
+
:fax => '+01123456789',
|
44
|
+
:phone => '+01123456789',
|
45
|
+
:address1 => '10 Example Road',
|
46
|
+
:address2 => 'Bar',
|
47
|
+
:city => 'Sampleville',
|
48
|
+
:company_name => 'Company Name',
|
49
|
+
:region => 'CA',
|
50
|
+
:postal_code => '94141',
|
51
|
+
:country_code => 'US',
|
52
|
+
}
|
53
|
+
|
54
|
+
@optional_fields = [ :fax, :phone, :address2, :company_name, :contact_name ]
|
55
|
+
|
56
|
+
@xml_str = %q{<?xml version="1.0" encoding="UTF-8" ?>
|
57
|
+
<root>
|
58
|
+
<some-address>
|
59
|
+
<contact-name>%s</contact-name>
|
60
|
+
<email>%s</email>
|
61
|
+
<fax>%s</fax>
|
62
|
+
<phone>%s</phone>
|
63
|
+
<address1>%s</address1>
|
64
|
+
<address2>%s</address2>
|
65
|
+
<city>%s</city>
|
66
|
+
<company-name>%s</company-name>
|
67
|
+
<region>%s</region>
|
68
|
+
<postal-code>%s</postal-code>
|
69
|
+
<country-code>%s</country-code>
|
70
|
+
</some-address>
|
71
|
+
</root>}
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_responds_correctly
|
75
|
+
@address = Address.new
|
76
|
+
|
77
|
+
@data.each do |key, value|
|
78
|
+
assert_respond_to @address, key, "key == #{key}"
|
79
|
+
assert_respond_to @address, "#{key}=".to_sym, "key == #{key}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_creating_address_with_full_fields_works
|
84
|
+
xml_str = @xml_str %
|
85
|
+
[
|
86
|
+
@data[:contact_name], @data[:email], @data[:fax], @data[:phone], @data[:address1],
|
87
|
+
@data[:address2], @data[:city], @data[:company_name], @data[:region],
|
88
|
+
@data[:postal_code], @data[:country_code]
|
89
|
+
]
|
90
|
+
|
91
|
+
document = REXML::Document.new(xml_str)
|
92
|
+
|
93
|
+
the_element = document.elements['/root/some-address']
|
94
|
+
|
95
|
+
address = Address.create_from_element(the_element)
|
96
|
+
|
97
|
+
@data.each do |key, value|
|
98
|
+
assert_equal value, address.send(key)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_creating_address_works_when_removing_optional_fields
|
103
|
+
@optional_fields.power.each do |optional_symbols|
|
104
|
+
xml_str = @xml_str %
|
105
|
+
[
|
106
|
+
@data[:contact_name], @data[:email], @data[:fax], @data[:phone], @data[:address1],
|
107
|
+
@data[:address2], @data[:city], @data[:company_name], @data[:region],
|
108
|
+
@data[:postal_code], @data[:country_code]
|
109
|
+
]
|
110
|
+
|
111
|
+
# Remove all optional symbols in this run.
|
112
|
+
optional_symbols.each do |symbol|
|
113
|
+
xml_str = xml_str.gsub(%r{<#{symbol.to_s.gsub('_', '-')}>.*?</#{symbol.to_s.gsub('_', '-')}>}, '')
|
114
|
+
end
|
115
|
+
|
116
|
+
document = REXML::Document.new(xml_str)
|
117
|
+
|
118
|
+
the_element = document.elements['/root/some-address']
|
119
|
+
|
120
|
+
address = Address.create_from_element(the_element)
|
121
|
+
|
122
|
+
@data.each do |key, value|
|
123
|
+
if optional_symbols.include?(key) then
|
124
|
+
assert_nil address.send(key)
|
125
|
+
else
|
126
|
+
assert_equal value, address.send(key)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|