xero_gateway-float 2.0.15
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +12 -0
- data/LICENSE +14 -0
- data/README.textile +357 -0
- data/Rakefile +14 -0
- data/examples/oauth.rb +25 -0
- data/examples/partner_app.rb +36 -0
- data/init.rb +1 -0
- data/lib/oauth/oauth_consumer.rb +14 -0
- data/lib/xero_gateway.rb +39 -0
- data/lib/xero_gateway/account.rb +95 -0
- data/lib/xero_gateway/accounts_list.rb +87 -0
- data/lib/xero_gateway/address.rb +96 -0
- data/lib/xero_gateway/bank_transaction.rb +178 -0
- data/lib/xero_gateway/ca-certificates.crt +2560 -0
- data/lib/xero_gateway/contact.rb +206 -0
- data/lib/xero_gateway/credit_note.rb +222 -0
- data/lib/xero_gateway/currency.rb +56 -0
- data/lib/xero_gateway/dates.rb +30 -0
- data/lib/xero_gateway/error.rb +18 -0
- data/lib/xero_gateway/exceptions.rb +46 -0
- data/lib/xero_gateway/gateway.rb +622 -0
- data/lib/xero_gateway/http.rb +138 -0
- data/lib/xero_gateway/http_encoding_helper.rb +49 -0
- data/lib/xero_gateway/invoice.rb +236 -0
- data/lib/xero_gateway/line_item.rb +125 -0
- data/lib/xero_gateway/line_item_calculations.rb +55 -0
- data/lib/xero_gateway/money.rb +16 -0
- data/lib/xero_gateway/oauth.rb +87 -0
- data/lib/xero_gateway/organisation.rb +75 -0
- data/lib/xero_gateway/partner_app.rb +30 -0
- data/lib/xero_gateway/payment.rb +40 -0
- data/lib/xero_gateway/phone.rb +77 -0
- data/lib/xero_gateway/private_app.rb +17 -0
- data/lib/xero_gateway/response.rb +41 -0
- data/lib/xero_gateway/tax_rate.rb +63 -0
- data/lib/xero_gateway/tracking_category.rb +87 -0
- data/test/integration/accounts_list_test.rb +109 -0
- data/test/integration/create_bank_transaction_test.rb +38 -0
- data/test/integration/create_contact_test.rb +66 -0
- data/test/integration/create_credit_note_test.rb +49 -0
- data/test/integration/create_invoice_test.rb +49 -0
- data/test/integration/get_accounts_test.rb +23 -0
- data/test/integration/get_bank_transaction_test.rb +51 -0
- data/test/integration/get_bank_transactions_test.rb +88 -0
- data/test/integration/get_contact_test.rb +28 -0
- data/test/integration/get_contacts_test.rb +40 -0
- data/test/integration/get_credit_note_test.rb +48 -0
- data/test/integration/get_credit_notes_test.rb +90 -0
- data/test/integration/get_currencies_test.rb +25 -0
- data/test/integration/get_invoice_test.rb +48 -0
- data/test/integration/get_invoices_test.rb +92 -0
- data/test/integration/get_organisation_test.rb +24 -0
- data/test/integration/get_tax_rates_test.rb +25 -0
- data/test/integration/get_tracking_categories_test.rb +27 -0
- data/test/integration/update_bank_transaction_test.rb +31 -0
- data/test/integration/update_contact_test.rb +31 -0
- data/test/integration/update_invoice_test.rb +31 -0
- data/test/test_helper.rb +179 -0
- data/test/unit/account_test.rb +47 -0
- data/test/unit/bank_transaction_test.rb +126 -0
- data/test/unit/contact_test.rb +97 -0
- data/test/unit/credit_note_test.rb +284 -0
- data/test/unit/currency_test.rb +31 -0
- data/test/unit/gateway_test.rb +119 -0
- data/test/unit/invoice_test.rb +326 -0
- data/test/unit/oauth_test.rb +116 -0
- data/test/unit/organisation_test.rb +38 -0
- data/test/unit/tax_rate_test.rb +38 -0
- data/test/unit/tracking_category_test.rb +52 -0
- data/xero_gateway.gemspec +15 -0
- metadata +164 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../test_helper.rb')
|
2
|
+
|
3
|
+
class CurrencyTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
# Tests that a currency can be converted into XML that Xero can understand, and then converted back to a currency
|
6
|
+
def test_build_and_parse_xml
|
7
|
+
currency = create_test_currency
|
8
|
+
|
9
|
+
# Generate the XML message
|
10
|
+
currency_as_xml = currency.to_xml
|
11
|
+
|
12
|
+
# Parse the XML message and retrieve the account element
|
13
|
+
currency_element = REXML::XPath.first(REXML::Document.new(currency_as_xml), "/Currency")
|
14
|
+
|
15
|
+
# Build a new account from the XML
|
16
|
+
result_currency = XeroGateway::Currency.from_xml(currency_element)
|
17
|
+
|
18
|
+
# Check the account details
|
19
|
+
assert_equal currency, result_currency
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def create_test_currency
|
26
|
+
XeroGateway::Currency.new.tap do |currency|
|
27
|
+
currency.code = "NZD"
|
28
|
+
currency.description = "New Zealand Dollar"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../test_helper.rb')
|
2
|
+
|
3
|
+
class GatewayTest < Test::Unit::TestCase
|
4
|
+
include TestHelper
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@gateway = XeroGateway::Gateway.new(CONSUMER_KEY, CONSUMER_SECRET)
|
8
|
+
end
|
9
|
+
|
10
|
+
context "with error handling" do
|
11
|
+
|
12
|
+
should "handle token expired" do
|
13
|
+
XeroGateway::OAuth.any_instance.stubs(:get).returns(stub(:plain_body => get_file_as_string("token_expired"), :code => "401"))
|
14
|
+
|
15
|
+
assert_raises XeroGateway::OAuth::TokenExpired do
|
16
|
+
@gateway.get_accounts
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
should "handle invalid request tokens" do
|
21
|
+
XeroGateway::OAuth.any_instance.stubs(:get).returns(stub(:plain_body => get_file_as_string("invalid_request_token"), :code => "401"))
|
22
|
+
|
23
|
+
assert_raises XeroGateway::OAuth::TokenInvalid do
|
24
|
+
@gateway.get_accounts
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
should "handle invalid consumer key" do
|
29
|
+
XeroGateway::OAuth.any_instance.stubs(:get).returns(stub(:plain_body => get_file_as_string("invalid_consumer_key"), :code => "401"))
|
30
|
+
|
31
|
+
assert_raises XeroGateway::OAuth::TokenInvalid do
|
32
|
+
@gateway.get_accounts
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
should "handle rate limit exceeded" do
|
37
|
+
XeroGateway::OAuth.any_instance.stubs(:get).returns(stub(:plain_body => get_file_as_string("rate_limit_exceeded"), :code => "401"))
|
38
|
+
|
39
|
+
assert_raises XeroGateway::OAuth::RateLimitExceeded do
|
40
|
+
@gateway.get_accounts
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
should "handle unknown errors" do
|
45
|
+
XeroGateway::OAuth.any_instance.stubs(:get).returns(stub(:plain_body => get_file_as_string("bogus_oauth_error"), :code => "401"))
|
46
|
+
|
47
|
+
assert_raises XeroGateway::OAuth::UnknownError do
|
48
|
+
@gateway.get_accounts
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
should "handle ApiExceptions" do
|
53
|
+
XeroGateway::OAuth.any_instance.stubs(:put).returns(stub(:plain_body => get_file_as_string("api_exception.xml"), :code => "400"))
|
54
|
+
|
55
|
+
assert_raises XeroGateway::ApiException do
|
56
|
+
@gateway.create_invoice(XeroGateway::Invoice.new)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
should "handle invoices not found" do
|
61
|
+
XeroGateway::OAuth.any_instance.stubs(:get).returns(stub(:plain_body => get_file_as_string("api_exception.xml"), :code => "404"))
|
62
|
+
|
63
|
+
assert_raises XeroGateway::InvoiceNotFoundError do
|
64
|
+
@gateway.get_invoice('unknown-invoice-id')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
should "handle bank transactions not found" do
|
69
|
+
XeroGateway::OAuth.any_instance.stubs(:get).returns(stub(:plain_body => get_file_as_string("api_exception.xml"), :code => "404"))
|
70
|
+
|
71
|
+
assert_raises XeroGateway::BankTransactionNotFoundError do
|
72
|
+
@gateway.get_bank_transaction('unknown-bank-transaction-id')
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
should "handle credit notes not found" do
|
77
|
+
XeroGateway::OAuth.any_instance.stubs(:get).returns(stub(:plain_body => get_file_as_string("api_exception.xml"), :code => "404"))
|
78
|
+
|
79
|
+
assert_raises XeroGateway::CreditNoteNotFoundError do
|
80
|
+
@gateway.get_credit_note('unknown-credit-note-id')
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
should "handle random root elements" do
|
85
|
+
XeroGateway::OAuth.any_instance.stubs(:put).returns(stub(:plain_body => "<RandomRootElement></RandomRootElement>", :code => "200"))
|
86
|
+
|
87
|
+
assert_raises XeroGateway::UnparseableResponse do
|
88
|
+
@gateway.create_invoice(XeroGateway::Invoice.new)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_unknown_error_handling
|
95
|
+
if STUB_XERO_CALLS
|
96
|
+
@gateway.xero_url = "DUMMY_URL"
|
97
|
+
@gateway.stubs(:http_get).with {|client, url, params| url =~ /Invoices\/AN_INVALID_ID$/ }.returns(get_file_as_string("unknown_error.xml"))
|
98
|
+
end
|
99
|
+
|
100
|
+
result = @gateway.get_invoice("AN_INVALID_ID")
|
101
|
+
assert !result.success?
|
102
|
+
assert_equal 1, result.errors.size
|
103
|
+
assert !result.errors.first.type.nil?
|
104
|
+
assert !result.errors.first.description.nil?
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_object_not_found_error_handling
|
108
|
+
if STUB_XERO_CALLS
|
109
|
+
@gateway.xero_url = "DUMMY_URL"
|
110
|
+
@gateway.stubs(:http_get).with {|client, url, params| url =~ /Invoices\/UNKNOWN_INVOICE_NO$/ }.returns(get_file_as_string("invoice_not_found_error.xml"))
|
111
|
+
end
|
112
|
+
|
113
|
+
result = @gateway.get_invoice("UNKNOWN_INVOICE_NO")
|
114
|
+
assert !result.success?
|
115
|
+
assert_equal 1, result.errors.size
|
116
|
+
assert_equal "Xero.API.Library.Exceptions.ObjectDoesNotExistException", result.errors.first.type
|
117
|
+
assert !result.errors.first.description.nil?
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,326 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../test_helper.rb')
|
2
|
+
|
3
|
+
class InvoiceTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "building and parsing XML" do
|
6
|
+
should "work vice versa" do
|
7
|
+
invoice = create_test_invoice
|
8
|
+
|
9
|
+
# Generate the XML message
|
10
|
+
invoice_as_xml = invoice.to_xml
|
11
|
+
|
12
|
+
# Parse the XML message and retrieve the invoice element
|
13
|
+
invoice_element = REXML::XPath.first(REXML::Document.new(invoice_as_xml), "/Invoice")
|
14
|
+
|
15
|
+
# Build a new invoice from the XML
|
16
|
+
result_invoice = XeroGateway::Invoice.from_xml(invoice_element)
|
17
|
+
|
18
|
+
assert_equal(invoice, result_invoice)
|
19
|
+
end
|
20
|
+
|
21
|
+
should "work for optional params" do
|
22
|
+
invoice = create_test_invoice(:url => 'http://example.com?with=params&and=more')
|
23
|
+
invoice_element = REXML::XPath.first(REXML::Document.new(invoice.to_xml), "/Invoice")
|
24
|
+
assert_match /<Url>http:\/\/example.com\?with=params&and=more<\/Url>/, invoice_element.to_s
|
25
|
+
|
26
|
+
parsed_invoice = XeroGateway::Invoice.from_xml(invoice_element)
|
27
|
+
assert_equal 'http://example.com?with=params&and=more', parsed_invoice.url
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Tests the sub_total calculation and that setting it manually doesn't modify the data.
|
32
|
+
def test_invoice_sub_total_calculation
|
33
|
+
invoice = create_test_invoice
|
34
|
+
line_item = invoice.line_items.first
|
35
|
+
|
36
|
+
# Make sure that everything adds up to begin with.
|
37
|
+
expected_sub_total = invoice.line_items.inject(BigDecimal.new('0')) { | sum, line_item | line_item.line_amount }
|
38
|
+
assert_equal(expected_sub_total, invoice.sub_total)
|
39
|
+
|
40
|
+
# Change the sub_total and check that it doesn't modify anything.
|
41
|
+
invoice.sub_total = expected_sub_total * 10
|
42
|
+
assert_equal(expected_sub_total, invoice.sub_total)
|
43
|
+
|
44
|
+
# Change the amount of the first line item and make sure that
|
45
|
+
# everything still continues to add up.
|
46
|
+
line_item.unit_amount = line_item.unit_amount + 10
|
47
|
+
assert_not_equal(expected_sub_total, invoice.sub_total)
|
48
|
+
expected_sub_total = invoice.line_items.inject(BigDecimal.new('0')) { | sum, line_item | line_item.line_amount }
|
49
|
+
assert_equal(expected_sub_total, invoice.sub_total)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Tests the total_tax calculation and that setting it manually doesn't modify the data.
|
53
|
+
def test_invoice_sub_total_calculation
|
54
|
+
invoice = create_test_invoice
|
55
|
+
line_item = invoice.line_items.first
|
56
|
+
|
57
|
+
# Make sure that everything adds up to begin with.
|
58
|
+
expected_total_tax = invoice.line_items.inject(BigDecimal.new('0')) { | sum, line_item | line_item.tax_amount }
|
59
|
+
assert_equal(expected_total_tax, invoice.total_tax)
|
60
|
+
|
61
|
+
# Change the total_tax and check that it doesn't modify anything.
|
62
|
+
invoice.total_tax = expected_total_tax * 10
|
63
|
+
assert_equal(expected_total_tax, invoice.total_tax)
|
64
|
+
|
65
|
+
# Change the tax_amount of the first line item and make sure that
|
66
|
+
# everything still continues to add up.
|
67
|
+
line_item.tax_amount = line_item.tax_amount + 10
|
68
|
+
assert_not_equal(expected_total_tax, invoice.total_tax)
|
69
|
+
expected_total_tax = invoice.line_items.inject(BigDecimal.new('0')) { | sum, line_item | line_item.tax_amount }
|
70
|
+
assert_equal(expected_total_tax, invoice.total_tax)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Tests the total calculation and that setting it manually doesn't modify the data.
|
74
|
+
def test_invoice_sub_total_calculation
|
75
|
+
invoice = create_test_invoice
|
76
|
+
line_item = invoice.line_items.first
|
77
|
+
|
78
|
+
# Make sure that everything adds up to begin with.
|
79
|
+
expected_total = invoice.sub_total + invoice.total_tax
|
80
|
+
assert_equal(expected_total, invoice.total)
|
81
|
+
|
82
|
+
# Change the total and check that it doesn't modify anything.
|
83
|
+
invoice.total = expected_total * 10
|
84
|
+
assert_equal(expected_total, invoice.total)
|
85
|
+
|
86
|
+
# Change the quantity of the first line item and make sure that
|
87
|
+
# everything still continues to add up.
|
88
|
+
line_item.quantity = line_item.quantity + 5
|
89
|
+
assert_not_equal(expected_total, invoice.total)
|
90
|
+
expected_total = invoice.sub_total + invoice.total_tax
|
91
|
+
assert_equal(expected_total, invoice.total)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Tests that the LineItem#line_amount calculation is working correctly.
|
95
|
+
def test_line_amount_calculation
|
96
|
+
invoice = create_test_invoice
|
97
|
+
line_item = invoice.line_items.first
|
98
|
+
|
99
|
+
# Make sure that everything adds up to begin with.
|
100
|
+
expected_amount = line_item.quantity * line_item.unit_amount
|
101
|
+
assert_equal(expected_amount, line_item.line_amount)
|
102
|
+
|
103
|
+
# Change the line_amount and check that it doesn't modify anything.
|
104
|
+
line_item.line_amount = expected_amount * 10
|
105
|
+
assert_equal(expected_amount, line_item.line_amount)
|
106
|
+
|
107
|
+
# Change the quantity and check that the line_amount has been updated.
|
108
|
+
quantity = line_item.quantity + 2
|
109
|
+
line_item.quantity = quantity
|
110
|
+
assert_not_equal(expected_amount, line_item.line_amount)
|
111
|
+
assert_equal(quantity * line_item.unit_amount, line_item.line_amount)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Ensure that the totalling methods don't raise exceptions, even when
|
115
|
+
# invoice.line_items is empty.
|
116
|
+
def test_totalling_methods_when_line_items_empty
|
117
|
+
invoice = create_test_invoice
|
118
|
+
invoice.line_items = []
|
119
|
+
|
120
|
+
assert_nothing_raised(Exception) {
|
121
|
+
assert_equal(BigDecimal.new('0'), invoice.sub_total)
|
122
|
+
assert_equal(BigDecimal.new('0'), invoice.total_tax)
|
123
|
+
assert_equal(BigDecimal.new('0'), invoice.total)
|
124
|
+
}
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_invoice_type_helper_methods
|
128
|
+
# Test accounts receivable invoices.
|
129
|
+
invoice = create_test_invoice({:invoice_type => 'ACCREC'})
|
130
|
+
assert_equal(true, invoice.accounts_receivable?, "Accounts RECEIVABLE invoice doesn't think it is.")
|
131
|
+
assert_equal(false, invoice.accounts_payable?, "Accounts RECEIVABLE invoice thinks it's payable.")
|
132
|
+
|
133
|
+
# Test accounts payable invoices.
|
134
|
+
invoice = create_test_invoice({:invoice_type => 'ACCPAY'})
|
135
|
+
assert_equal(false, invoice.accounts_receivable?, "Accounts PAYABLE invoice doesn't think it is.")
|
136
|
+
assert_equal(true, invoice.accounts_payable?, "Accounts PAYABLE invoice thinks it's receivable.")
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
# Make sure that the create_test_invoice method is working correctly
|
141
|
+
# with all the defaults and overrides.
|
142
|
+
def test_create_test_invoice_defaults_working
|
143
|
+
invoice = create_test_invoice
|
144
|
+
|
145
|
+
# Test invoice defaults.
|
146
|
+
assert_equal('ACCREC', invoice.invoice_type)
|
147
|
+
assert_kind_of(Date, invoice.date)
|
148
|
+
assert_kind_of(Date, invoice.due_date)
|
149
|
+
assert_equal('12345', invoice.invoice_number)
|
150
|
+
assert_equal('MY REFERENCE FOR THIS INVOICE', invoice.reference)
|
151
|
+
assert_equal("Exclusive", invoice.line_amount_types)
|
152
|
+
|
153
|
+
# Test the contact defaults.
|
154
|
+
assert_equal('00000000-0000-0000-0000-000000000000', invoice.contact.contact_id)
|
155
|
+
assert_equal('CONTACT NAME', invoice.contact.name)
|
156
|
+
|
157
|
+
# Test address defaults.
|
158
|
+
assert_equal('DEFAULT', invoice.contact.address.address_type)
|
159
|
+
assert_equal('LINE 1 OF THE ADDRESS', invoice.contact.address.line_1)
|
160
|
+
|
161
|
+
# Test phone defaults.
|
162
|
+
assert_equal('DEFAULT', invoice.contact.phone.phone_type)
|
163
|
+
assert_equal('12345678', invoice.contact.phone.number)
|
164
|
+
|
165
|
+
# Test the line_item defaults.
|
166
|
+
assert_equal('A LINE ITEM', invoice.line_items.first.description)
|
167
|
+
assert_equal('200', invoice.line_items.first.account_code)
|
168
|
+
assert_equal(BigDecimal.new('100'), invoice.line_items.first.unit_amount)
|
169
|
+
assert_equal(BigDecimal.new('12.5'), invoice.line_items.first.tax_amount)
|
170
|
+
|
171
|
+
# Test optional params
|
172
|
+
assert_nil invoice.url
|
173
|
+
|
174
|
+
# Test overriding an invoice parameter (assume works for all).
|
175
|
+
invoice = create_test_invoice({:invoice_type => 'ACCPAY'})
|
176
|
+
assert_equal('ACCPAY', invoice.invoice_type)
|
177
|
+
|
178
|
+
# Test overriding a contact/address/phone parameter (assume works for all).
|
179
|
+
invoice = create_test_invoice({}, {:name => 'OVERRIDDEN NAME', :address => {:line_1 => 'OVERRIDDEN LINE 1'}, :phone => {:number => '999'}})
|
180
|
+
assert_equal('OVERRIDDEN NAME', invoice.contact.name)
|
181
|
+
assert_equal('OVERRIDDEN LINE 1', invoice.contact.address.line_1)
|
182
|
+
assert_equal('999', invoice.contact.phone.number)
|
183
|
+
|
184
|
+
# Test overriding line_items with hash.
|
185
|
+
invoice = create_test_invoice({}, {}, {:description => 'OVERRIDDEN LINE ITEM'})
|
186
|
+
assert_equal(1, invoice.line_items.size)
|
187
|
+
assert_equal('OVERRIDDEN LINE ITEM', invoice.line_items.first.description)
|
188
|
+
assert_equal(BigDecimal.new('100'), invoice.line_items.first.unit_amount)
|
189
|
+
|
190
|
+
# Test overriding line_items with array of 2 line_items.
|
191
|
+
invoice = create_test_invoice({}, {}, [
|
192
|
+
{:description => 'OVERRIDDEN ITEM 1'},
|
193
|
+
{:description => 'OVERRIDDEN ITEM 2', :account_code => '200', :unit_amount => BigDecimal.new('200'), :tax_amount => '25.0'}
|
194
|
+
])
|
195
|
+
assert_equal(2, invoice.line_items.size)
|
196
|
+
assert_equal('OVERRIDDEN ITEM 1', invoice.line_items[0].description)
|
197
|
+
assert_equal(BigDecimal.new('100'), invoice.line_items[0].unit_amount)
|
198
|
+
assert_equal('OVERRIDDEN ITEM 2', invoice.line_items[1].description)
|
199
|
+
assert_equal(BigDecimal.new('200'), invoice.line_items[1].unit_amount)
|
200
|
+
end
|
201
|
+
|
202
|
+
def test_auto_creation_of_associated_contact
|
203
|
+
invoice = create_test_invoice({}, nil) # no contact
|
204
|
+
assert_nil(invoice.instance_variable_get("@contact"))
|
205
|
+
|
206
|
+
new_contact = invoice.contact
|
207
|
+
assert_kind_of(XeroGateway::Contact, new_contact)
|
208
|
+
end
|
209
|
+
|
210
|
+
def test_add_line_item
|
211
|
+
invoice = create_test_invoice({}, {}, nil) # no line_items
|
212
|
+
assert_equal(0, invoice.line_items.size)
|
213
|
+
|
214
|
+
line_item_params = {:description => "Test Item 1", :unit_amount => 100}
|
215
|
+
|
216
|
+
# Test adding line item by hash
|
217
|
+
line_item = invoice.add_line_item(line_item_params)
|
218
|
+
assert_kind_of(XeroGateway::LineItem, line_item)
|
219
|
+
assert_equal(line_item_params[:description], line_item.description)
|
220
|
+
assert_equal(line_item_params[:unit_amount], line_item.unit_amount)
|
221
|
+
assert_equal(1, invoice.line_items.size)
|
222
|
+
|
223
|
+
# Test adding line item by XeroGateway::LineItem
|
224
|
+
line_item = invoice.add_line_item(line_item_params)
|
225
|
+
assert_kind_of(XeroGateway::LineItem, line_item)
|
226
|
+
assert_equal(line_item_params[:description], line_item.description)
|
227
|
+
assert_equal(line_item_params[:unit_amount], line_item.unit_amount)
|
228
|
+
assert_equal(2, invoice.line_items.size)
|
229
|
+
|
230
|
+
# Test that pushing anything else into add_line_item fails.
|
231
|
+
["invalid", 100, nil, []].each do | invalid_object |
|
232
|
+
assert_raise(XeroGateway::Invoice::InvalidLineItemError) { invoice.add_line_item(invalid_object) }
|
233
|
+
assert_equal(2, invoice.line_items.size)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
def test_instantiate_invoice_with_default_line_amount_types
|
238
|
+
invoice = XeroGateway::Invoice.new
|
239
|
+
assert_equal(invoice.line_amount_types, 'Exclusive')
|
240
|
+
end
|
241
|
+
|
242
|
+
def test_optional_params
|
243
|
+
invoice = create_test_invoice(:url => 'http://example.com')
|
244
|
+
assert_equal 'http://example.com', invoice.url
|
245
|
+
end
|
246
|
+
|
247
|
+
private
|
248
|
+
|
249
|
+
def create_test_invoice(invoice_params = {}, contact_params = {}, line_item_params = [])
|
250
|
+
unless invoice_params.nil?
|
251
|
+
invoice_params = {
|
252
|
+
:invoice_type => 'ACCREC',
|
253
|
+
:date => Date.today,
|
254
|
+
:due_date => Date.today + 10, # 10 days in the future
|
255
|
+
:invoice_number => '12345',
|
256
|
+
:reference => "MY REFERENCE FOR THIS INVOICE",
|
257
|
+
:line_amount_types => "Exclusive"
|
258
|
+
}.merge(invoice_params)
|
259
|
+
end
|
260
|
+
invoice = XeroGateway::Invoice.new(invoice_params || {})
|
261
|
+
|
262
|
+
unless contact_params.nil?
|
263
|
+
# Strip out :address key from contact_params to use as the default address.
|
264
|
+
stripped_address = {
|
265
|
+
:address_type => 'DEFAULT',
|
266
|
+
:line_1 => 'LINE 1 OF THE ADDRESS'
|
267
|
+
}.merge(contact_params.delete(:address) || {})
|
268
|
+
|
269
|
+
# Strip out :phone key from contact_params to use at the default phone.
|
270
|
+
stripped_phone = {
|
271
|
+
:phone_type => 'DEFAULT',
|
272
|
+
:number => '12345678'
|
273
|
+
}.merge(contact_params.delete(:phone) || {})
|
274
|
+
|
275
|
+
contact_params = {
|
276
|
+
:contact_id => '00000000-0000-0000-0000-000000000000', # Just any valid GUID
|
277
|
+
:name => "CONTACT NAME",
|
278
|
+
:first_name => "Bob",
|
279
|
+
:last_name => "Builder"
|
280
|
+
}.merge(contact_params)
|
281
|
+
|
282
|
+
# Create invoice.contact from contact_params.
|
283
|
+
invoice.contact = XeroGateway::Contact.new(contact_params)
|
284
|
+
invoice.contact.address = XeroGateway::Address.new(stripped_address)
|
285
|
+
invoice.contact.phone = XeroGateway::Phone.new(stripped_phone)
|
286
|
+
end
|
287
|
+
|
288
|
+
unless line_item_params.nil?
|
289
|
+
line_item_params = [line_item_params].flatten # always use an array, even if only a single hash passed in
|
290
|
+
|
291
|
+
# At least one line item, make first have some defaults.
|
292
|
+
line_item_params << {} if line_item_params.size == 0
|
293
|
+
line_item_params[0] = {
|
294
|
+
:description => "A LINE ITEM",
|
295
|
+
:account_code => "200",
|
296
|
+
:unit_amount => BigDecimal.new("100"),
|
297
|
+
:tax_amount => BigDecimal.new("12.5"),
|
298
|
+
:tracking => XeroGateway::TrackingCategory.new(:name => "blah", :options => "hello")
|
299
|
+
}.merge(line_item_params[0])
|
300
|
+
|
301
|
+
# Create invoice.line_items from line_item_params
|
302
|
+
line_item_params.each do | line_item |
|
303
|
+
invoice.add_line_item(line_item)
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
invoice
|
308
|
+
end
|
309
|
+
|
310
|
+
# NB: Xero no longer appears to provide XSDs for their api, check http://blog.xero.com/developer/api/invoices/
|
311
|
+
#
|
312
|
+
# context "validating against the Xero XSD" do
|
313
|
+
# setup do
|
314
|
+
# # @schema = LibXML::XML::Schema.document(LibXML::XML::Document.file(File.join(File.dirname(__FILE__), '../xsd/create_invoice.xsd')))
|
315
|
+
# end
|
316
|
+
#
|
317
|
+
# should "succeed" do
|
318
|
+
# invoice = create_test_invoice
|
319
|
+
# message = invoice.to_xml
|
320
|
+
#
|
321
|
+
# # Check that the document matches the XSD
|
322
|
+
# assert LibXML::XML::Parser.string(message).parse.validate_schema(@schema), "The XML document generated did not validate against the XSD"
|
323
|
+
# end
|
324
|
+
# end
|
325
|
+
|
326
|
+
end
|