tlconnor-xero_gateway 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -13,7 +13,6 @@ module XeroGateway
13
13
 
14
14
  def initialize(params = {})
15
15
  params.each do |k,v|
16
- self.instance_variable_set("@#{k}", v) ## create and initialize an instance variable for this key/value pair
17
16
  self.send("#{k}=", v)
18
17
  end
19
18
 
@@ -29,4 +28,4 @@ module XeroGateway
29
28
  errors.blank? ? nil : errors[0]
30
29
  end
31
30
  end
32
- end
31
+ end
@@ -5,21 +5,15 @@ module XeroGateway
5
5
  def initialize(params = {})
6
6
  @options = []
7
7
  params.each do |k,v|
8
- self.instance_variable_set("@#{k}", v) ## create and initialize an instance variable for this key/value pair
9
8
  self.send("#{k}=", v)
10
9
  end
11
10
  end
12
11
 
13
- def ==(other)
14
- [:name, :options].each do |field|
15
- return false if send(field) != other.send(field)
16
- end
17
- return true
12
+ def option
13
+ options[0] if options.size == 1
18
14
  end
19
-
20
- def to_xml
21
- b = Builder::XmlMarkup.new
22
-
15
+
16
+ def to_xml(b = Builder::XmlMarkup.new)
23
17
  b.TrackingCategory {
24
18
  b.Name self.name
25
19
  b.Options {
@@ -41,6 +35,13 @@ module XeroGateway
41
35
  end
42
36
  end
43
37
  tracking_category
44
- end
38
+ end
39
+
40
+ def ==(other)
41
+ [:name, :options].each do |field|
42
+ return false if send(field) != other.send(field)
43
+ end
44
+ return true
45
+ end
45
46
  end
46
- end
47
+ end
@@ -0,0 +1,111 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class AccountsListTest < Test::Unit::TestCase
4
+ include TestHelper
5
+
6
+ def setup
7
+ @gateway = XeroGateway::Gateway.new(
8
+ :customer_key => CUSTOMER_KEY,
9
+ :api_key => API_KEY
10
+ )
11
+
12
+ # Always stub out calls for this integration test as we need to be able to control the data.
13
+ @gateway.xero_url = "DUMMY_URL"
14
+ @gateway.stubs(:http_get).with {|url, params| url =~ /accounts$/ }.returns(get_file_as_string("accounts.xml"))
15
+ end
16
+
17
+ def test_get_accounts_list
18
+ accounts_list = @gateway.get_accounts_list
19
+ assert_not_equal(0, accounts_list.accounts.size)
20
+ end
21
+
22
+ # Make sure that the list is loaded when finding things.
23
+ def test_raise_error_on_not_loaded
24
+ accounts_list = @gateway.get_accounts_list(false)
25
+ assert_equal(false, accounts_list.loaded?)
26
+ assert_raise(XeroGateway::AccountsList::AccountsListNotLoadedError) { accounts_list[200] }
27
+ assert_raise(XeroGateway::AccountsList::AccountsListNotLoadedError) { accounts_list.find_by_code(200) }
28
+ assert_raise(XeroGateway::AccountsList::AccountsListNotLoadedError) { accounts_list.find_all_by_type('EXPENSE') }
29
+ assert_raise(XeroGateway::AccountsList::AccountsListNotLoadedError) { accounts_list.find_all_by_tax_type('OUTPUT') }
30
+ end
31
+
32
+ # Test simple lookup by account code (from cache).
33
+ def test_simple_lookup_by_account_code
34
+ accounts_list = @gateway.get_accounts_list
35
+ assert_equal(true, accounts_list.loaded?)
36
+
37
+ # Load data in the stubbed response.
38
+ expected_accounts = accounts_as_array
39
+
40
+ # Make sure that every single expected account exists in the cached lookup hash.
41
+ expected_accounts.each do | expected_account |
42
+ found_account = accounts_list.find_by_code(expected_account.code)
43
+ assert_kind_of(XeroGateway::Account, found_account)
44
+ assert(expected_account == found_account, "Found account does not match expected account.")
45
+
46
+ found_account_shortcut = accounts_list[expected_account.code]
47
+ assert_kind_of(XeroGateway::Account, found_account_shortcut)
48
+ assert(expected_account == found_account_shortcut, "Found account does not match expected account (shortcut).")
49
+ end
50
+ end
51
+
52
+ # Test finding accounts by their account type (from cache).
53
+ def test_lookup_by_account_type
54
+ accounts_list = @gateway.get_accounts_list
55
+ assert_equal(true, accounts_list.loaded?)
56
+
57
+ # Load data in the stubbed response.
58
+ expected_accounts = accounts_as_array
59
+
60
+ # Get all the unique account types present in the expected accounts data along with their counts.
61
+ unique_types = expected_accounts.inject({}) do | list, account |
62
+ list[account.type] = 0 if list[account.type].nil?
63
+ list[account.type] += 1
64
+ list
65
+ end
66
+
67
+ assert_not_equal(0, unique_types)
68
+ unique_types.each do | account_type, count |
69
+ found_accounts = accounts_list.find_all_by_type(account_type)
70
+ assert_equal(count, found_accounts.size)
71
+ found_accounts.each do | found_account |
72
+ assert_kind_of(XeroGateway::Account, found_account)
73
+ assert_equal(account_type, found_account.type)
74
+ end
75
+ end
76
+ end
77
+
78
+ # Test finding accounts by their tax type (from cache).
79
+ def test_lookup_by_tax_type
80
+ accounts_list = @gateway.get_accounts_list
81
+ assert_equal(true, accounts_list.loaded?)
82
+
83
+ # Load data in the stubbed response.
84
+ expected_accounts = accounts_as_array
85
+
86
+ # Get all the unique tax types present in the expected accounts data along with their counts.
87
+ unique_types = expected_accounts.inject({}) do | list, account |
88
+ list[account.tax_type] = 0 if list[account.tax_type].nil?
89
+ list[account.tax_type] += 1
90
+ list
91
+ end
92
+
93
+ assert_not_equal(0, unique_types)
94
+ unique_types.each do | tax_type, count |
95
+ found_accounts = accounts_list.find_all_by_tax_type(tax_type)
96
+ assert_equal(count, found_accounts.size)
97
+ found_accounts.each do | found_account |
98
+ assert_kind_of(XeroGateway::Account, found_account)
99
+ assert_equal(tax_type, found_account.tax_type)
100
+ end
101
+ end
102
+ end
103
+
104
+ private
105
+
106
+ def accounts_as_array
107
+ response = @gateway.__send__(:parse_response, get_file_as_string("accounts.xml"))
108
+ response.accounts
109
+ end
110
+
111
+ end
@@ -13,17 +13,57 @@ class CreateContactTest < Test::Unit::TestCase
13
13
  @gateway.xero_url = "DUMMY_URL"
14
14
 
15
15
  @gateway.stubs(:http_put).with {|url, body, params| url =~ /contact$/ }.returns(get_file_as_string("contact.xml"))
16
+ @gateway.stubs(:http_post).with {|url, body, params| url =~ /contact$/ }.returns(get_file_as_string("contact.xml"))
16
17
  end
17
18
  end
18
19
 
19
20
  def test_create_contact
20
- example_contact = dummy_contact
21
+ example_contact = dummy_contact.dup
21
22
 
22
23
  result = @gateway.create_contact(example_contact)
23
- assert result.success?
24
- assert !result.contact.contact_id.nil?
25
- assert !result.request_xml.nil?
26
- assert !result.response_xml.nil?
27
- assert_equal result.contact.name, example_contact.name
24
+ assert_valid_contact_save_response(result, example_contact)
28
25
  end
26
+
27
+ def test_create_from_contact
28
+ example_contact = dummy_contact.dup
29
+
30
+ contact = @gateway.build_contact(example_contact)
31
+ result = contact.create
32
+ assert_valid_contact_save_response(result, example_contact)
33
+ end
34
+
35
+ def test_update_from_contact
36
+ example_contact = dummy_contact.dup
37
+
38
+ contact = @gateway.build_contact(example_contact)
39
+ contact.create # need to create first so we have a ContactID
40
+
41
+ result = contact.update
42
+ assert_valid_contact_save_response(result, example_contact)
43
+ end
44
+
45
+ def test_save_from_contact
46
+ example_contact = dummy_contact.dup
47
+
48
+ contact = @gateway.build_contact(example_contact)
49
+ result = contact.save
50
+ assert_valid_contact_save_response(result, example_contact)
51
+ end
52
+
53
+ def test_create_contact_valid
54
+ example_contact = dummy_contact.dup
55
+ assert_equal true, example_contact.valid?, "contact is invalid - errors:\n\t#{example_contact.errors.map { | error | "#{error[0]} #{error[1]}"}.join("\n\t")}"
56
+ end
57
+
58
+ private
59
+
60
+ def assert_valid_contact_save_response(result, example_contact)
61
+ assert_kind_of XeroGateway::Response, result
62
+ assert result.success?
63
+ assert !result.contact.contact_id.nil?
64
+ assert !result.request_xml.nil?
65
+ assert !result.response_xml.nil?
66
+ assert_equal result.contact.name, example_contact.name
67
+ assert example_contact.contact_id =~ GUID_REGEX
68
+ end
29
69
  end
@@ -13,17 +13,40 @@ class CreateInvoiceTest < Test::Unit::TestCase
13
13
  @gateway.xero_url = "DUMMY_URL"
14
14
 
15
15
  @gateway.stubs(:http_put).with {|url, body, params| url =~ /invoice$/ }.returns(get_file_as_string("invoice.xml"))
16
+ @gateway.stubs(:http_post).with {|url, body, params| url =~ /invoice$/ }.returns(get_file_as_string("invoice.xml"))
16
17
  end
17
18
  end
18
19
 
19
20
  def test_create_invoice
20
- example_invoice = dummy_invoice
21
+ example_invoice = dummy_invoice.dup
21
22
 
22
23
  result = @gateway.create_invoice(example_invoice)
23
- assert result.success?
24
- assert !result.request_xml.nil?
25
- assert !result.response_xml.nil?
26
- assert !result.invoice.invoice_id.nil?
27
- assert result.invoice.invoice_number == example_invoice.invoice_number
24
+ assert_valid_invoice_save_response(result, example_invoice)
28
25
  end
26
+
27
+ def test_create_from_invoice
28
+ example_invoice = dummy_invoice.dup
29
+
30
+ invoice = @gateway.build_invoice(example_invoice)
31
+ result = invoice.create
32
+ assert_valid_invoice_save_response(result, example_invoice)
33
+ end
34
+
35
+ def test_create_invoice_valid
36
+ example_invoice = dummy_invoice.dup
37
+ assert_equal true, example_invoice.valid?, "invoice is invalid - errors:\n\t#{example_invoice.errors.map { | error | "#{error[0]} #{error[1]}"}.join("\n\t")}"
38
+ end
39
+
40
+ private
41
+
42
+ def assert_valid_invoice_save_response(result, example_invoice)
43
+ assert_kind_of XeroGateway::Response, result
44
+ assert result.success?
45
+ assert !result.request_xml.nil?
46
+ assert !result.response_xml.nil?
47
+ assert !result.invoice.invoice_id.nil?
48
+ assert result.invoice.invoice_number == example_invoice.invoice_number
49
+ assert example_invoice.invoice_id =~ GUID_REGEX
50
+ end
51
+
29
52
  end
data/test/test_helper.rb CHANGED
@@ -20,6 +20,9 @@ module TestHelper
20
20
 
21
21
  API_KEY = ENV["API_KEY"] unless defined? API_KEY
22
22
  CUSTOMER_KEY = ENV["CUSTOMER_KEY"] unless defined? CUSTOMER_KEY
23
+
24
+ # Helper constant for checking regex
25
+ GUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/ unless defined?(GUID_REGEX)
23
26
 
24
27
 
25
28
  def dummy_invoice
@@ -28,22 +31,18 @@ module TestHelper
28
31
  :due_date => Date.today + 20,
29
32
  :invoice_number => STUB_XERO_CALLS ? "INV-0001" : "#{Time.now.to_f}",
30
33
  :reference => "YOUR REFERENCE (NOT NECESSARILY UNIQUE!)",
31
- :sub_total => 1000,
32
- :total_tax => 125,
33
- :total => 1125
34
34
  })
35
35
  invoice.contact = dummy_contact
36
36
  invoice.line_items << XeroGateway::LineItem.new(
37
37
  :description => "THE DESCRIPTION OF THE LINE ITEM",
38
38
  :unit_amount => 1000,
39
39
  :tax_amount => 125,
40
- :line_amount => 1000,
41
40
  :tracking_category => "THE TRACKING CATEGORY FOR THE LINE ITEM",
42
41
  :tracking_option => "THE TRACKING OPTION FOR THE LINE ITEM"
43
42
  )
44
43
  invoice
45
44
  end
46
-
45
+
47
46
  def dummy_contact
48
47
  unique_id = Time.now.to_f
49
48
  contact = XeroGateway::Contact.new(:name => STUB_XERO_CALLS ? "CONTACT NAME" : "THE NAME OF THE CONTACT #{unique_id}")
@@ -32,6 +32,49 @@ class ContactTest < Test::Unit::TestCase
32
32
  assert_equal contact, result_contact
33
33
  end
34
34
 
35
+ # Test Contact#add_address helper creates a valid XeroGateway::Contact object with the passed in values
36
+ # and appends it to the Contact#addresses attribute.
37
+ def test_add_address_helper
38
+ contact = create_test_contact
39
+ assert_equal(1, contact.addresses.size)
40
+
41
+ new_values = {
42
+ :address_type => 'POBOX',
43
+ :line_1 => 'NEW LINE 1',
44
+ :line_2 => 'NEW LINE 2',
45
+ :line_3 => 'NEW LINE 3',
46
+ :line_4 => 'NEW LINE 4',
47
+ :city => 'NEW CITY',
48
+ :region => 'NEW REGION',
49
+ :post_code => '5555',
50
+ :country => 'Australia'
51
+ }
52
+ contact.add_address(new_values)
53
+
54
+ assert_equal(2, contact.addresses.size)
55
+ assert_kind_of(XeroGateway::Address, contact.addresses.last)
56
+ new_values.each { |k,v| assert_equal(v, contact.addresses.last.send("#{k}")) }
57
+ end
58
+
59
+ # Test Contact#add_phone helper creates a valid XeroGateway::Phone object with the passed in values
60
+ # and appends it to the Contact#phones attribute.
61
+ def test_add_address_helper
62
+ contact = create_test_contact
63
+ assert_equal(1, contact.phones.size)
64
+
65
+ new_values = {
66
+ :phone_type => 'MOBILE',
67
+ :country_code => '61',
68
+ :area_code => '406',
69
+ :number => '123456'
70
+ }
71
+ contact.add_phone(new_values)
72
+
73
+ assert_equal(2, contact.phones.size)
74
+ assert_kind_of(XeroGateway::Phone, contact.phones.last)
75
+ new_values.each { |k,v| assert_equal(v, contact.phones.last.send("#{k}")) }
76
+ end
77
+
35
78
 
36
79
  private
37
80
 
@@ -1,6 +1,7 @@
1
1
  require File.join(File.dirname(__FILE__), '../test_helper.rb')
2
2
 
3
3
  class InvoiceTest < Test::Unit::TestCase
4
+
4
5
  def setup
5
6
  @schema = LibXML::XML::Schema.document(LibXML::XML::Document.file(File.join(File.dirname(__FILE__), '../xsd/create_invoice.xsd')))
6
7
  end
@@ -31,33 +32,225 @@ class InvoiceTest < Test::Unit::TestCase
31
32
  assert_equal(invoice, result_invoice)
32
33
  end
33
34
 
35
+ # Tests the sub_total calculation and that setting it manually doesn't modify the data.
36
+ def test_invoice_sub_total_calculation
37
+ invoice = create_test_invoice
38
+ line_item = invoice.line_items.first
39
+
40
+ # Make sure that everything adds up to begin with.
41
+ expected_sub_total = invoice.line_items.inject(BigDecimal.new('0')) { | sum, line_item | line_item.line_amount }
42
+ assert_equal(expected_sub_total, invoice.sub_total)
43
+
44
+ # Change the sub_total and check that it doesn't modify anything.
45
+ invoice.sub_total = expected_sub_total * 10
46
+ assert_equal(expected_sub_total, invoice.sub_total)
47
+
48
+ # Change the amount of the first line item and make sure that
49
+ # everything still continues to add up.
50
+ line_item.unit_amount = line_item.unit_amount + 10
51
+ assert_not_equal(expected_sub_total, invoice.sub_total)
52
+ expected_sub_total = invoice.line_items.inject(BigDecimal.new('0')) { | sum, line_item | line_item.line_amount }
53
+ assert_equal(expected_sub_total, invoice.sub_total)
54
+ end
34
55
 
35
- private
56
+ # Tests the total_tax calculation and that setting it manually doesn't modify the data.
57
+ def test_invoice_sub_total_calculation
58
+ invoice = create_test_invoice
59
+ line_item = invoice.line_items.first
60
+
61
+ # Make sure that everything adds up to begin with.
62
+ expected_total_tax = invoice.line_items.inject(BigDecimal.new('0')) { | sum, line_item | line_item.tax_amount }
63
+ assert_equal(expected_total_tax, invoice.total_tax)
64
+
65
+ # Change the total_tax and check that it doesn't modify anything.
66
+ invoice.total_tax = expected_total_tax * 10
67
+ assert_equal(expected_total_tax, invoice.total_tax)
68
+
69
+ # Change the tax_amount of the first line item and make sure that
70
+ # everything still continues to add up.
71
+ line_item.tax_amount = line_item.tax_amount + 10
72
+ assert_not_equal(expected_total_tax, invoice.total_tax)
73
+ expected_total_tax = invoice.line_items.inject(BigDecimal.new('0')) { | sum, line_item | line_item.tax_amount }
74
+ assert_equal(expected_total_tax, invoice.total_tax)
75
+ end
76
+
77
+ # Tests the total calculation and that setting it manually doesn't modify the data.
78
+ def test_invoice_sub_total_calculation
79
+ invoice = create_test_invoice
80
+ line_item = invoice.line_items.first
81
+
82
+ # Make sure that everything adds up to begin with.
83
+ expected_total = invoice.sub_total + invoice.total_tax
84
+ assert_equal(expected_total, invoice.total)
85
+
86
+ # Change the total and check that it doesn't modify anything.
87
+ invoice.total = expected_total * 10
88
+ assert_equal(expected_total, invoice.total)
89
+
90
+ # Change the quantity of the first line item and make sure that
91
+ # everything still continues to add up.
92
+ line_item.quantity = line_item.quantity + 5
93
+ assert_not_equal(expected_total, invoice.total)
94
+ expected_total = invoice.sub_total + invoice.total_tax
95
+ assert_equal(expected_total, invoice.total)
96
+ end
97
+
98
+ # Tests that the LineItem#line_amount calculation is working correctly.
99
+ def test_line_amount_calculation
100
+ invoice = create_test_invoice
101
+ line_item = invoice.line_items.first
102
+
103
+ # Make sure that everything adds up to begin with.
104
+ expected_amount = line_item.quantity * line_item.unit_amount
105
+ assert_equal(expected_amount, line_item.line_amount)
106
+
107
+ # Change the line_amount and check that it doesn't modify anything.
108
+ line_item.line_amount = expected_amount * 10
109
+ assert_equal(expected_amount, line_item.line_amount)
110
+
111
+ # Change the quantity and check that the line_amount has been updated.
112
+ quantity = line_item.quantity + 2
113
+ line_item.quantity = quantity
114
+ assert_not_equal(expected_amount, line_item.line_amount)
115
+ assert_equal(quantity * line_item.unit_amount, line_item.line_amount)
116
+ end
117
+
118
+ # Ensure that the totalling methods don't raise exceptions, even when
119
+ # invoice.line_items is empty.
120
+ def test_totalling_methods_when_line_items_empty
121
+ invoice = create_test_invoice
122
+ invoice.line_items = []
123
+
124
+ assert_nothing_raised(Exception) {
125
+ assert_equal(BigDecimal.new('0'), invoice.sub_total)
126
+ assert_equal(BigDecimal.new('0'), invoice.total_tax)
127
+ assert_equal(BigDecimal.new('0'), invoice.total)
128
+ }
129
+ end
130
+
131
+ def test_invoice_type_helper_methods
132
+ # Test accounts receivable invoices.
133
+ invoice = create_test_invoice({:invoice_type => 'ACCREC'})
134
+ assert_equal(true, invoice.accounts_receivable?, "Accounts RECEIVABLE invoice doesn't think it is.")
135
+ assert_equal(false, invoice.accounts_payable?, "Accounts RECEIVABLE invoice thinks it's payable.")
136
+
137
+ # Test accounts payable invoices.
138
+ invoice = create_test_invoice({:invoice_type => 'ACCPAY'})
139
+ assert_equal(false, invoice.accounts_receivable?, "Accounts PAYABLE invoice doesn't think it is.")
140
+ assert_equal(true, invoice.accounts_payable?, "Accounts PAYABLE invoice thinks it's receivable.")
141
+ end
36
142
 
37
- def create_test_invoice
38
- invoice = XeroGateway::Invoice.new(:invoice_type => "THE INVOICE TYPE")
39
- invoice.date = Time.now
40
- invoice.due_date = Time.now + 10
41
- invoice.invoice_number = "12345"
42
- invoice.reference = "MY REFERENCE FOR THIS INVOICE"
43
- invoice.includes_tax = false
44
- invoice.sub_total = BigDecimal.new("1000")
45
- invoice.total_tax = BigDecimal.new("125")
46
- invoice.total = BigDecimal.new("1125")
47
-
48
- invoice.contact = XeroGateway::Contact.new(:contact_id => 55555)
49
- invoice.contact.name = "CONTACT NAME"
50
- invoice.contact.address.address_type = "THE ADDRESS TYPE FOR THE CONTACT"
51
- invoice.contact.address.line_1 = "LINE 1 OF THE ADDRESS"
52
- invoice.contact.phone.number = "12345"
53
-
54
- invoice.line_items << XeroGateway::LineItem.new({
143
+
144
+ # Make sure that the create_test_invoice method is working correctly
145
+ # with all the defaults and overrides.
146
+ def test_create_test_invoice_defaults_working
147
+ invoice = create_test_invoice
148
+
149
+ # Test invoice defaults.
150
+ assert_equal('ACCREC', invoice.invoice_type)
151
+ assert_kind_of(Time, invoice.date)
152
+ assert_kind_of(Time, invoice.due_date)
153
+ assert_equal('12345', invoice.invoice_number)
154
+ assert_equal('MY REFERENCE FOR THIS INVOICE', invoice.reference)
155
+ assert_equal(false, invoice.includes_tax)
156
+
157
+ # Test the contact defaults.
158
+ assert_equal('00000000-0000-0000-0000-000000000000', invoice.contact.contact_id)
159
+ assert_equal('CONTACT NAME', invoice.contact.name)
160
+
161
+ # Test address defaults.
162
+ assert_equal('DEFAULT', invoice.contact.address.address_type)
163
+ assert_equal('LINE 1 OF THE ADDRESS', invoice.contact.address.line_1)
164
+
165
+ # Test phone defaults.
166
+ assert_equal('DEFAULT', invoice.contact.phone.phone_type)
167
+ assert_equal('12345678', invoice.contact.phone.number)
168
+
169
+ # Test the line_item defaults.
170
+ assert_equal('A LINE ITEM', invoice.line_items.first.description)
171
+ assert_equal('200', invoice.line_items.first.account_code)
172
+ assert_equal(BigDecimal.new('100'), invoice.line_items.first.unit_amount)
173
+ assert_equal(BigDecimal.new('12.5'), invoice.line_items.first.tax_amount)
174
+
175
+ # Test overriding an invoice parameter (assume works for all).
176
+ invoice = create_test_invoice({:invoice_type => 'ACCPAY'})
177
+ assert_equal('ACCPAY', invoice.invoice_type)
178
+
179
+ # Test overriding a contact/address/phone parameter (assume works for all).
180
+ invoice = create_test_invoice({}, {:name => 'OVERRIDDEN NAME', :address => {:line_1 => 'OVERRIDDEN LINE 1'}, :phone => {:number => '999'}})
181
+ assert_equal('OVERRIDDEN NAME', invoice.contact.name)
182
+ assert_equal('OVERRIDDEN LINE 1', invoice.contact.address.line_1)
183
+ assert_equal('999', invoice.contact.phone.number)
184
+
185
+ # Test overriding line_items with hash.
186
+ invoice = create_test_invoice({}, {}, {:description => 'OVERRIDDEN LINE ITEM'})
187
+ assert_equal(1, invoice.line_items.size)
188
+ assert_equal('OVERRIDDEN LINE ITEM', invoice.line_items.first.description)
189
+ assert_equal(BigDecimal.new('100'), invoice.line_items.first.unit_amount)
190
+
191
+ # Test overriding line_items with array of 2 line_items.
192
+ invoice = create_test_invoice({}, {}, [
193
+ {:description => 'OVERRIDDEN ITEM 1'},
194
+ {:description => 'OVERRIDDEN ITEM 2', :account_code => '200', :unit_amount => BigDecimal.new('200'), :tax_amount => '25.0'}
195
+ ])
196
+ assert_equal(2, invoice.line_items.size)
197
+ assert_equal('OVERRIDDEN ITEM 1', invoice.line_items[0].description)
198
+ assert_equal(BigDecimal.new('100'), invoice.line_items[0].unit_amount)
199
+ assert_equal('OVERRIDDEN ITEM 2', invoice.line_items[1].description)
200
+ assert_equal(BigDecimal.new('200'), invoice.line_items[1].unit_amount)
201
+ end
202
+
203
+ private
204
+
205
+ def create_test_invoice(invoice_params = {}, contact_params = {}, line_item_params = [])
206
+ invoice_params = {
207
+ :invoice_type => 'ACCREC',
208
+ :date => Time.now,
209
+ :due_date => Time.now + (10 * 24 * 3600), # 10 days in the future
210
+ :invoice_number => '12345',
211
+ :reference => "MY REFERENCE FOR THIS INVOICE",
212
+ :includes_tax => false
213
+ }.merge(invoice_params)
214
+ invoice = XeroGateway::Invoice.new(invoice_params)
215
+
216
+ # Strip out :address key from contact_params to use as the default address.
217
+ stripped_address = {
218
+ :address_type => 'DEFAULT',
219
+ :line_1 => 'LINE 1 OF THE ADDRESS'
220
+ }.merge(contact_params.delete(:address) || {})
221
+
222
+ # Strip out :phone key from contact_params to use at the default phone.
223
+ stripped_phone = {
224
+ :phone_type => 'DEFAULT',
225
+ :number => '12345678'
226
+ }.merge(contact_params.delete(:phone) || {})
227
+
228
+ contact_params = {
229
+ :contact_id => '00000000-0000-0000-0000-000000000000', # Just any valid GUID
230
+ :name => "CONTACT NAME"
231
+ }.merge(contact_params)
232
+
233
+ # Create invoice.contact from contact_params.
234
+ invoice.contact = XeroGateway::Contact.new(contact_params)
235
+ invoice.contact.address = XeroGateway::Address.new(stripped_address)
236
+ invoice.contact.phone = XeroGateway::Phone.new(stripped_phone)
237
+
238
+ line_item_params = [line_item_params].flatten # always use an array, even if only a single hash passed in
239
+
240
+ # At least one line item, make first have some defaults.
241
+ line_item_params << {} if line_item_params.size == 0
242
+ line_item_params[0] = {
55
243
  :description => "A LINE ITEM",
56
244
  :account_code => "200",
57
245
  :unit_amount => BigDecimal.new("100"),
58
- :tax_amount => BigDecimal.new("12.5"),
59
- :line_amount => BigDecimal.new("125")
60
- })
246
+ :tax_amount => BigDecimal.new("12.5")
247
+ }.merge(line_item_params[0])
248
+
249
+ # Create invoice.line_items from line_item_params
250
+ line_item_params.each do | line_item |
251
+ invoice.line_items << XeroGateway::LineItem.new(line_item)
252
+ end
253
+
61
254
  invoice
62
255
  end
63
256
  end