test/unit/invoice_test.rb in xero_gateway-2.3.0 vs test/unit/invoice_test.rb in xero_gateway-2.4.0

- old
+ new

@@ -1,18 +1,49 @@ require File.join(File.dirname(__FILE__), '../test_helper.rb') class InvoiceTest < Test::Unit::TestCase context "with line item totals" do + setup do + # make sure the invoices think they have a gateway + @invoice = create_test_invoice( + invoice_id: "a99a9aaa-9999-99a9-9aa9-aaaaaa9a9999", + line_items_downloaded: false, + total: 6_969_00, + total_tax: 1_045.35, + sub_total: 5_923.65 + ) + @invoice.gateway = stub + end should "allow setting and reading these as instance variables without downloading line items" do - invoice = create_test_invoice(:line_items_downloaded => false, :total => 6969_00) + assert !@invoice.line_items_downloaded? - assert !invoice.line_items_downloaded? XeroGateway::Invoice.any_instance.expects(:download_line_items).never - assert_equal 6969_00, invoice.total + assert_equal 6969_00, @invoice.total + assert_equal 1_045.35, @invoice.total_tax + assert_equal 5_923.65, @invoice.sub_total end + + should "download line items if we call #line_items" do + XeroGateway::Invoice.any_instance.expects(:download_line_items).once.returns([]) + assert_equal [], @invoice.line_items + end + + should "also work when creating an invoice from XML" do + invoices_response_xml = File.open(File.join(File.dirname(__FILE__), "..", "stub_responses", "invoices.xml")).read + invoice_element = REXML::XPath.first(REXML::Document.new(invoices_response_xml), "/Response/Invoices/Invoice") + from_xml = XeroGateway::Invoice.from_xml(invoice_element) + from_xml.gateway = stub() + + assert !from_xml.line_items_downloaded? + XeroGateway::Invoice.any_instance.expects(:download_line_items).never + assert_equal 1125.0, from_xml.total + assert_equal 125.0, from_xml.total_tax + assert_equal 1000.0, from_xml.sub_total + end + end context "building and parsing XML" do should "work vice versa" do invoice = create_test_invoice @@ -30,74 +61,74 @@ end should "work for optional params" do invoice = create_test_invoice(:url => 'http://example.com?with=params&and=more') invoice_element = REXML::XPath.first(REXML::Document.new(invoice.to_xml), "/Invoice") - assert_match /<Url>http:\/\/example.com\?with=params&amp;and=more<\/Url>/, invoice_element.to_s + assert_match(/<Url>http:\/\/example.com\?with=params&amp;and=more<\/Url>/, invoice_element.to_s) parsed_invoice = XeroGateway::Invoice.from_xml(invoice_element) assert_equal 'http://example.com?with=params&and=more', parsed_invoice.url end end # Tests the sub_total calculation and that setting it manually doesn't modify the data. def test_invoice_sub_total_calculation invoice = create_test_invoice(:line_items_downloaded => true) line_item = invoice.line_items.first - + # Make sure that everything adds up to begin with. - expected_sub_total = invoice.line_items.inject(BigDecimal.new('0')) { | sum, line_item | line_item.line_amount } + expected_sub_total = invoice.line_items.inject(BigDecimal.new('0')) { | sum, l | l.line_amount } assert_equal(expected_sub_total, invoice.sub_total) - + # Change the sub_total and check that it doesn't modify anything. invoice.sub_total = expected_sub_total * 10 assert_equal(expected_sub_total, invoice.sub_total) - - # Change the amount of the first line item and make sure that + + # Change the amount of the first line item and make sure that # everything still continues to add up. line_item.unit_amount = line_item.unit_amount + 10 assert_not_equal(expected_sub_total, invoice.sub_total) - expected_sub_total = invoice.line_items.inject(BigDecimal.new('0')) { | sum, line_item | line_item.line_amount } + expected_sub_total = invoice.line_items.inject(BigDecimal.new('0')) { | sum, l | l.line_amount } assert_equal(expected_sub_total, invoice.sub_total) end - + # Tests the total_tax calculation and that setting it manually doesn't modify the data. def test_invoice_sub_total_calculation2 invoice = create_test_invoice(:line_items_downloaded => true) line_item = invoice.line_items.first - + # Make sure that everything adds up to begin with. - expected_total_tax = invoice.line_items.inject(BigDecimal.new('0')) { | sum, line_item | line_item.tax_amount } + expected_total_tax = invoice.line_items.inject(BigDecimal.new('0')) { | sum, l | l.tax_amount } assert_equal(expected_total_tax, invoice.total_tax) - + # Change the total_tax and check that it doesn't modify anything. invoice.total_tax = expected_total_tax * 10 assert_equal(expected_total_tax, invoice.total_tax) - - # Change the tax_amount of the first line item and make sure that + + # Change the tax_amount of the first line item and make sure that # everything still continues to add up. line_item.tax_amount = line_item.tax_amount + 10 assert_not_equal(expected_total_tax, invoice.total_tax) - expected_total_tax = invoice.line_items.inject(BigDecimal.new('0')) { | sum, line_item | line_item.tax_amount } + expected_total_tax = invoice.line_items.inject(BigDecimal.new('0')) { | sum, l | l.tax_amount } assert_equal(expected_total_tax, invoice.total_tax) end # Tests the total calculation and that setting it manually doesn't modify the data. def test_invoice_sub_total_calculation3 invoice = create_test_invoice(:line_items_downloaded => true) assert invoice.line_items_downloaded? line_item = invoice.line_items.first - + # Make sure that everything adds up to begin with. expected_total = invoice.sub_total + invoice.total_tax assert_equal(expected_total, invoice.total) - + # Change the total and check that it doesn't modify anything. invoice.total = expected_total * 10 assert_equal(expected_total.to_f, invoice.total.to_f) - - # Change the quantity of the first line item and make sure that + + # Change the quantity of the first line item and make sure that # everything still continues to add up. line_item.quantity = line_item.quantity + 5 assert_not_equal(expected_total, invoice.total) expected_total = invoice.sub_total + invoice.total_tax assert_equal(expected_total, invoice.total) @@ -105,78 +136,78 @@ # Tests that the LineItem#line_amount calculation is working correctly. def test_line_amount_calculation invoice = create_test_invoice line_item = invoice.line_items.first - + # Make sure that everything adds up to begin with. expected_amount = line_item.quantity * line_item.unit_amount assert_equal(expected_amount, line_item.line_amount) - + # Change the line_amount and check that it doesn't modify anything. line_item.line_amount = expected_amount * 10 assert_equal(expected_amount, line_item.line_amount) - + # Change the quantity and check that the line_amount has been updated. quantity = line_item.quantity + 2 line_item.quantity = quantity assert_not_equal(expected_amount, line_item.line_amount) assert_equal(quantity * line_item.unit_amount, line_item.line_amount) end - + # Ensure that the totalling methods don't raise exceptions, even when # invoice.line_items is empty. def test_totalling_methods_when_line_items_empty invoice = create_test_invoice invoice.line_items = [] - + assert_nothing_raised(Exception) { assert_equal(BigDecimal.new('0'), invoice.sub_total) assert_equal(BigDecimal.new('0'), invoice.total_tax) assert_equal(BigDecimal.new('0'), invoice.total) } end - + def test_invoice_type_helper_methods # Test accounts receivable invoices. invoice = create_test_invoice({:invoice_type => 'ACCREC'}) assert_equal(true, invoice.accounts_receivable?, "Accounts RECEIVABLE invoice doesn't think it is.") assert_equal(false, invoice.accounts_payable?, "Accounts RECEIVABLE invoice thinks it's payable.") - + # Test accounts payable invoices. invoice = create_test_invoice({:invoice_type => 'ACCPAY'}) assert_equal(false, invoice.accounts_receivable?, "Accounts PAYABLE invoice doesn't think it is.") assert_equal(true, invoice.accounts_payable?, "Accounts PAYABLE invoice thinks it's receivable.") end - - + + # Make sure that the create_test_invoice method is working correctly # with all the defaults and overrides. def test_create_test_invoice_defaults_working invoice = create_test_invoice - + # Test invoice defaults. assert_equal('ACCREC', invoice.invoice_type) assert_kind_of(Date, invoice.date) assert_kind_of(Date, invoice.due_date) assert_kind_of(Time, invoice.updated_date_utc) assert_equal('12345', invoice.invoice_number) assert_equal('MY REFERENCE FOR THIS INVOICE', invoice.reference) assert_equal("Exclusive", invoice.line_amount_types) - + # Test the contact defaults. assert_equal('00000000-0000-0000-0000-000000000000', invoice.contact.contact_id) assert_equal('CONTACT NAME', invoice.contact.name) - + # Test address defaults. assert_equal('DEFAULT', invoice.contact.address.address_type) assert_equal('LINE 1 OF THE ADDRESS', invoice.contact.address.line_1) - + # Test phone defaults. assert_equal('DEFAULT', invoice.contact.phone.phone_type) assert_equal('12345678', invoice.contact.phone.number) - + # Test the line_item defaults. assert_equal('A LINE ITEM', invoice.line_items.first.description) assert_equal('200', invoice.line_items.first.account_code) assert_equal(BigDecimal.new('100'), invoice.line_items.first.unit_amount) assert_equal(BigDecimal.new('12.5'), invoice.line_items.first.tax_amount) @@ -185,23 +216,23 @@ assert_nil invoice.url # Test overriding an invoice parameter (assume works for all). invoice = create_test_invoice({:invoice_type => 'ACCPAY'}) assert_equal('ACCPAY', invoice.invoice_type) - + # Test overriding a contact/address/phone parameter (assume works for all). invoice = create_test_invoice({}, {:name => 'OVERRIDDEN NAME', :address => {:line_1 => 'OVERRIDDEN LINE 1'}, :phone => {:number => '999'}}) assert_equal('OVERRIDDEN NAME', invoice.contact.name) assert_equal('OVERRIDDEN LINE 1', invoice.contact.address.line_1) assert_equal('999', invoice.contact.phone.number) - + # Test overriding line_items with hash. invoice = create_test_invoice({}, {}, {:description => 'OVERRIDDEN LINE ITEM'}) assert_equal(1, invoice.line_items.size) assert_equal('OVERRIDDEN LINE ITEM', invoice.line_items.first.description) assert_equal(BigDecimal.new('100'), invoice.line_items.first.unit_amount) - + # Test overriding line_items with array of 2 line_items. invoice = create_test_invoice({}, {}, [ {:description => 'OVERRIDDEN ITEM 1'}, {:description => 'OVERRIDDEN ITEM 2', :account_code => '200', :unit_amount => BigDecimal.new('200'), :tax_amount => '25.0'} ]) @@ -209,32 +240,32 @@ assert_equal('OVERRIDDEN ITEM 1', invoice.line_items[0].description) assert_equal(BigDecimal.new('100'), invoice.line_items[0].unit_amount) assert_equal('OVERRIDDEN ITEM 2', invoice.line_items[1].description) assert_equal(BigDecimal.new('200'), invoice.line_items[1].unit_amount) end - + def test_auto_creation_of_associated_contact invoice = create_test_invoice({}, nil) # no contact - assert_nil(invoice.instance_variable_get("@contact")) - + assert(!invoice.instance_variable_defined?("@contact")) + new_contact = invoice.contact assert_kind_of(XeroGateway::Contact, new_contact) end - + def test_add_line_item invoice = create_test_invoice({}, {}, nil) # no line_items assert_equal(0, invoice.line_items.size) - + line_item_params = {:description => "Test Item 1", :unit_amount => 100} - + # Test adding line item by hash line_item = invoice.add_line_item(line_item_params) assert_kind_of(XeroGateway::LineItem, line_item) assert_equal(line_item_params[:description], line_item.description) assert_equal(line_item_params[:unit_amount], line_item.unit_amount) assert_equal(1, invoice.line_items.size) - + # Test adding line item by XeroGateway::LineItem line_item = invoice.add_line_item(line_item_params) assert_kind_of(XeroGateway::LineItem, line_item) assert_equal(line_item_params[:description], line_item.description) assert_equal(line_item_params[:unit_amount], line_item.unit_amount) @@ -251,23 +282,28 @@ invoice = XeroGateway::Invoice.new assert_equal(invoice.line_amount_types, 'Exclusive') end def test_optional_params - invoice = create_test_invoice(:url => 'http://example.com', :branding_theme_id => 'a94a78db-5cc6-4e26-a52b-045237e56e6e') + eur_code = "EUR" + eur_rate = 1.80 + + invoice = create_test_invoice(:url => 'http://example.com', :branding_theme_id => 'a94a78db-5cc6-4e26-a52b-045237e56e6e', :currency_code => eur_code, :currency_rate => eur_rate) assert_equal 'http://example.com', invoice.url assert_equal 'a94a78db-5cc6-4e26-a52b-045237e56e6e', invoice.branding_theme_id + assert_equal eur_code, invoice.currency_code + assert_equal eur_rate, invoice.currency_rate end def test_updated_date_utc time = Time.now.utc invoice = create_test_invoice(:updated_date_utc => time) assert_equal time, invoice.updated_date_utc end private - + def create_test_invoice(invoice_params = {}, contact_params = {}, line_item_params = []) unless invoice_params.nil? invoice_params = { :invoice_type => 'ACCREC', :date => Date.today, @@ -277,55 +313,55 @@ :line_amount_types => "Exclusive", :updated_date_utc => Time.now.utc }.merge(invoice_params) end invoice = XeroGateway::Invoice.new(invoice_params || {}) - + unless contact_params.nil? # Strip out :address key from contact_params to use as the default address. stripped_address = { :address_type => 'DEFAULT', :line_1 => 'LINE 1 OF THE ADDRESS' }.merge(contact_params.delete(:address) || {}) - + # Strip out :phone key from contact_params to use at the default phone. stripped_phone = { :phone_type => 'DEFAULT', :number => '12345678' }.merge(contact_params.delete(:phone) || {}) - + contact_params = { :contact_id => '00000000-0000-0000-0000-000000000000', # Just any valid GUID :name => "CONTACT NAME", :first_name => "Bob", :last_name => "Builder" }.merge(contact_params) - + # Create invoice.contact from contact_params. invoice.contact = XeroGateway::Contact.new(contact_params) invoice.contact.address = XeroGateway::Address.new(stripped_address) invoice.contact.phone = XeroGateway::Phone.new(stripped_phone) end - + unless line_item_params.nil? line_item_params = [line_item_params].flatten # always use an array, even if only a single hash passed in - + # At least one line item, make first have some defaults. line_item_params << {} if line_item_params.size == 0 line_item_params[0] = { :description => "A LINE ITEM", :account_code => "200", :unit_amount => BigDecimal.new("100"), :tax_amount => BigDecimal.new("12.5"), :tracking => XeroGateway::TrackingCategory.new(:name => "blah", :options => "hello") }.merge(line_item_params[0]) - + # Create invoice.line_items from line_item_params line_item_params.each do | line_item | invoice.add_line_item(line_item) end end - + invoice end # NB: Xero no longer appears to provide XSDs for their api, check http://blog.xero.com/developer/api/invoices/ #