# frozen_string_literal: true
require 'spec_helper'
module Payday # rubocop:todo Metrics/ModuleLength
describe Invoice do
# rubocop:todo RSpec/MultipleExpectations
it 'is able to be initialized with a hash of options' do # rubocop:todo RSpec/ExampleLength, RSpec/MultipleExpectations
# rubocop:enable RSpec/MultipleExpectations
i = described_class.new(invoice_number: 20, bill_to: 'Here', ship_to: 'There',
notes: 'These are some notes.',
line_items:
[LineItem.new(price: 10, quantity: 3, description: 'Shirts')],
shipping_rate: 15.00, shipping_description: 'USPS Priority Mail:',
tax_rate: 0.125, tax_description: 'Local Sales Tax, 12.5%',
invoice_date: Date.civil(1993, 4, 12))
expect(i.invoice_number).to eq(20)
expect(i.bill_to).to eq('Here')
expect(i.ship_to).to eq('There')
expect(i.notes).to eq('These are some notes.')
expect(i.line_items[0].description).to eq('Shirts')
expect(i.shipping_rate).to eq(BigDecimal('15.00'))
expect(i.shipping_description).to eq('USPS Priority Mail:')
expect(i.tax_rate).to eq(BigDecimal('0.125'))
expect(i.tax_description).to eq('Local Sales Tax, 12.5%')
expect(i.invoice_date).to eq(Date.civil(1993, 4, 12))
end
it 'totals all of the line items into a subtotal correctly' do # rubocop:todo RSpec/ExampleLength
i = described_class.new
# $100 in Pants
i.line_items << LineItem.new(price: 20, quantity: 5, description: 'Pants')
# $30 in Shirts
i.line_items <<
LineItem.new(price: 10, quantity: 3, description: 'Shirts')
# $1000 in Hats
i.line_items << LineItem.new(price: 5, quantity: 200, description: 'Hats')
expect(i.subtotal).to eq(BigDecimal(1130))
end
it 'calculates the correct tax rounded to two decimal places' do
i = described_class.new(tax_rate: 10.0)
i.line_items << LineItem.new(price: 20, quantity: 5, description: 'Pants')
expect(i.tax).to eq(BigDecimal(10))
end
it 'does not apply taxes to invoices with subtotal <= 0' do
i = described_class.new(tax_rate: 10.0)
i.line_items << LineItem.new(price: -1, quantity: 100,
description: 'Negative Priced Pants')
expect(i.tax).to eq(BigDecimal('-10'))
end
it 'calculates the total for an invoice correctly' do # rubocop:todo RSpec/ExampleLength
i = described_class.new(tax_rate: 10.0)
# $100 in Pants
i.line_items << LineItem.new(price: 20, quantity: 5, description: 'Pants')
# $30 in Shirts
i.line_items <<
LineItem.new(price: 10, quantity: 3, description: 'Shirts')
# $1000 in Hats
i.line_items << LineItem.new(price: 5, quantity: 200, description: 'Hats')
expect(i.total).to eq(BigDecimal(1243))
end
it "is overdue when it's past date and unpaid" do
i = described_class.new(due_at: Date.today - 1)
expect(i.overdue?).to be(true)
end
it "isn't overdue when past due date and paid" do
i = described_class.new(due_at: Date.today - 1, paid_at: Date.today)
expect(i.overdue?).not_to be(true)
end
it 'is overdue when due date is a time before the current date' do
i = described_class.new(due_at: Time.parse('Jan 1 14:33:20 GMT 2011'))
expect(i.overdue?).to be(true)
end
it 'is not refunded when not marked refunded' do
i = described_class.new
expect(i.refunded?).not_to be(true)
end
it 'is refunded when marked as refunded' do
i = described_class.new(refunded_at: Date.today)
expect(i.refunded?).to be(true)
end
it 'is not paid when not marked paid' do
i = described_class.new
expect(i.paid?).not_to be(true)
end
it 'is paid when marked as paid' do
i = described_class.new(paid_at: Date.today)
expect(i.paid?).to be(true)
end
# rubocop:todo RSpec/MultipleExpectations
it 'is able to iterate over details' do # rubocop:todo RSpec/ExampleLength, RSpec/MultipleExpectations
# rubocop:enable RSpec/MultipleExpectations
i = described_class.new(invoice_details: [%w[Test Yes], %w[Awesome Absolutely]])
details = []
i.each_detail do |key, value|
details << [key, value]
end
expect(details.length).to eq(2)
expect(details).to include(%w[Test Yes])
expect(details).to include(%w[Awesome Absolutely])
end
# rubocop:todo RSpec/MultipleExpectations
it 'is able to iterate through invoice_details as a hash' do # rubocop:todo RSpec/ExampleLength, RSpec/MultipleExpectations
# rubocop:enable RSpec/MultipleExpectations
i = described_class.new(invoice_details:
{'Test' => 'Yes', 'Awesome' => 'Absolutely'})
details = []
i.each_detail do |key, value|
details << [key, value]
end
expect(details.length).to eq(2)
expect(details).to include(%w[Test Yes])
expect(details).to include(%w[Awesome Absolutely])
end
describe 'rendering' do
before do
FileUtils.mkdir_p('tmp')
Config.default.reset
end
let(:invoice) { new_invoice(invoice_params) }
let(:invoice_params) { {} }
it 'renders to a file' do
FileUtils.rm_rf('tmp/testing.pdf')
invoice.render_pdf_to_file('tmp/testing.pdf')
expect(File.exist?('tmp/testing.pdf')).to be true
end
context 'with some invoice details' do
let(:invoice_params) do
{
invoice_details: {
'Ordered By:' => 'Alan Johnson',
'Paid By:' => 'Dude McDude'
}
}
end
it 'renders an invoice correctly' do # rubocop:todo RSpec/ExampleLength
Payday::Config.default.company_details = <<-DETAILS
10 This Way
Manhattan, NY 10001
800-111-2222
awesome@awesomecorp.com
DETAILS
invoice.line_items += [
LineItem.new(price: 20, quantity: 5, description: 'Pants'),
LineItem.new(price: 10, quantity: 3, description: 'Shirts'),
LineItem.new(price: 5, quantity: 200, description: 'Hats')
] * 30
expect(invoice.render_pdf).to match_binary_asset 'testing.pdf'
end
end
context 'with the locale set to Spanish' do
it 'renders and invoice in Spanish' do # rubocop:todo RSpec/ExampleLength
I18n.with_locale :es do
Payday::Config.default.company_details = 'Dirección'
invoice.line_items += [
LineItem.new(price: 20, quantity: 5, description: 'Pantalones'),
LineItem.new(price: 5, quantity: 200, description: 'Sombreros')
]
expect(invoice.render_pdf).to match_binary_asset 'testing_es.pdf'
end
end
end
context 'with a mix of LineItems with price, quantity and predefined_amounts' do
let(:invoice_params) do
{
invoice_details: {
'Ordered By:' => 'Alan Johnson',
'Paid By:' => 'Dude McDude'
}
}
end
it 'renders an invoice correctly' do # rubocop:todo RSpec/ExampleLength
Payday::Config.default.company_details = <<-DETAILS
10 This Way
Manhattan, NY 10001
800-111-2222
awesome@awesomecorp.com
DETAILS
invoice.add_line_item(price: 10, quantity: 3, description: 'Extra Users')
invoice.add_line_item(predefined_amount: 79,
description: "Flat Fee\nFrom date to date")
expect(invoice.render_pdf).to match_binary_asset 'testing_predefined_amount.pdf'
end
end
context 'paid, with an svg logo' do # rubocop:todo RSpec/ContextWording
before do
logo = {filename: 'spec/assets/tiger.svg', size: '100x100'}
Payday::Config.default.invoice_logo = logo
end
let(:invoice_params) { {paid_at: Date.civil(2012, 2, 22)} }
it 'renders an invoice correctly' do # rubocop:todo RSpec/ExampleLength
invoice.line_items += [
LineItem.new(price: 20, quantity: 5, description: 'Pants'),
LineItem.new(price: 10, quantity: 3, description: 'Shirts'),
LineItem.new(price: 5, quantity: 200.0, description: 'Hats')
] * 3
expect(invoice.render_pdf).to match_binary_asset 'svg.pdf'
end
end
def new_invoice(params = {})
default_params = {
tax_rate: 0.1,
notes: 'These are some crazy awesome notes with color!',
invoice_number: 12,
invoice_date: Date.civil(2011, 1, 1),
due_at: Date.civil(2011, 1, 22),
bill_to: "Alan Johnson\n101 This Way\nSomewhere, SC 22222",
ship_to: "Frank Johnson\n101 That Way\nOther, SC 22229"
}
Invoice.new(default_params.merge(params))
end
end
end
end