xero_gateway-float 2.0.15
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/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
|