installment-calculations
Version:
Calculate payment installments (and other useful details) based on start/end dates, interval and target amount
205 lines (179 loc) • 9.47 kB
JavaScript
var chai = require('chai');
chai.use(require('chai-datetime'));
var expect = chai.expect;
var IC = require('../index');
var moment = require('moment');
describe('getTransactionsArray', function() {
it('should calculate correct MONTHLY dates/amounts when a date of the 30th is provided', function() {
const startDate = moment().year(2015).month(0).date(30).toDate();
const dateTarget = moment().year(2015).month(11).date(31).toDate();
const savingsTarget = 1025;
const depositInterval = 'MONTHLY';
const transArr = IC.getTransactionsArray(savingsTarget, dateTarget, startDate, depositInterval);
const amounts = transArr.map(function(x) { return x.amount; });
const days = transArr.map(function(x) { return moment(x.date).format('D'); });
const months = transArr.map(function(x) { return moment(x.date).format('M'); });
expect(transArr.length).to.equal(12);
expect(amounts).to.eql([90, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85]);
expect(days).to.eql(['30', '28', '30', '30', '30', '30', '30', '30', '30', '30', '30', '30']);
expect(months).to.eql(['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12']);
});
it('should calculate correct MONTHLY dates/amounts when a date of the 31th is provided', function() {
const startDate = moment().year(2015).month(0).date(31).toDate();
const dateTarget = moment().year(2015).month(11).date(15).toDate();
const savingsTarget = 1025;
const depositInterval = 'MONTHLY';
const transArr = IC.getTransactionsArray(savingsTarget, dateTarget, startDate, depositInterval);
const amounts = transArr.map(function(x) { return x.amount; });
const days = transArr.map(function(x) { return moment(x.date).format('D'); });
const months = transArr.map(function(x) { return moment(x.date).format('M'); });
expect(transArr.length).to.equal(11);
expect(amounts).to.eql([95, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93]);
expect(days).to.eql(['31', '28', '31', '30', '31', '30', '31', '31', '30', '31', '30']);
expect(months).to.eql(['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11']);
});
it('should return array of objects with date and amount values for a WEEKLY interval', function() {
const startDate = moment().year(2015).month(0).date(1).toDate();
const dateTarget = moment().year(2015).month(2).date(8).toDate();
const savingsTarget = 1025;
const depositInterval = 'WEEKLY';
const transArr = IC.getTransactionsArray(savingsTarget, dateTarget, startDate, depositInterval);
const amounts = transArr.map(function(x) { return x.amount; });
const days = transArr.map(function(x) { return moment(x.date).format('D'); });
const months = transArr.map(function(x) { return moment(x.date).format('M'); });
expect(amounts).to.eql([107, 102, 102, 102, 102, 102, 102, 102, 102, 102]);
expect(days).to.eql(['1', '8', '15', '22', '29', '5', '12', '19', '26', '5']);
expect(months).to.eql(['1', '1', '1', '1', '1', '2', '2', '2', '2', '3']);
});
});
describe('numberOfWeeksBetween', function() {
it('should return the number of full weeks between two dates', function() {
const startDate = moment().year(2015).month(1).date(1).toDate();
const endDate = moment().year(2016).month(1).date(1).toDate();
const weeksBetween = IC.numberOfWeeksBetween(startDate, endDate);
expect(weeksBetween).to.equal(52);
});
it('should return a negative number of weeks when end date is before start date', function() {
const endDate = moment().year(2015).month(1).date(1).toDate();
const startDate = moment().year(2016).month(1).date(1).toDate();
const weeksBetween = IC.numberOfWeeksBetween(startDate, endDate);
expect(weeksBetween).to.equal(-52);
});
it('should return 0 when start and end is on the same week', function() {
const startDate = moment().year(2015).month(1).date(1).toDate();
const endDate = startDate;
const weeksBetween = IC.numberOfWeeksBetween(startDate, endDate);
expect(weeksBetween).to.equal(0);
});
});
describe('numberOfMonthsBetween', function() {
it('should return the number of full months between two dates', function() {
const startDate = moment().year(2015).month(1).date(1).toDate();
const endDate = moment().year(2016).month(1).date(1).toDate();
const monthsBetween = IC.numberOfMonthsBetween(startDate, endDate);
expect(monthsBetween).to.equal(12);
});
it('should return a negative number of months when end date is before start date', function() {
const endDate = moment().year(2015).month(1).date(1).toDate();
const startDate = moment().year(2016).month(1).date(1).toDate();
const monthsBetween = IC.numberOfMonthsBetween(startDate, endDate);
expect(monthsBetween).to.equal(-12);
});
it('should return 0 when start and end is on the same month', function() {
const startDate = moment().year(2015).month(1).date(1).toDate();
const endDate = startDate;
const monthsBetween = IC.numberOfMonthsBetween(startDate, endDate);
expect(monthsBetween).to.equal(0);
});
});
describe('getNextInstanceOfDate', function() {
it('should return the next occurence when in the month after', function() {
const startDate = moment().year(2015).month(0).date(1).startOf('day').toDate();
const expectedDate = moment().year(2015).month(1).date(1).startOf('day').toDate();
const nextInstanceOfDate = IC.getNextInstanceOfDate(1, startDate);
expect(nextInstanceOfDate).to.equalDate(expectedDate);
});
it('should return the next occurence when in the same month', function() {
const startDate = moment().year(2015).month(0).date(1).startOf('day').toDate();
const expectedDate = moment().year(2015).month(0).date(25).startOf('day').toDate();
const nextInstanceOfDate = IC.getNextInstanceOfDate(25, startDate);
expect(nextInstanceOfDate).to.equalDate(expectedDate);
});
});
describe('getNextInstanceOfDay', function() {
it('should return the next weekday occurence when in the week after', function() {
// Week 1 Thursday
const startDate = moment().year(2015).month(0).date(1).startOf('day').toDate();
// Week 2 Tuesday
const expectedDate = moment().year(2015).month(0).date(6).startOf('day').toDate();
const nextInstanceOfDay = IC.getNextInstanceOfDay(2, startDate);
expect(nextInstanceOfDay).to.equalDate(expectedDate);
});
it('should return the next weekday occurence when in the same week', function() {
// Week 2 Tuesday
const startDate = moment().year(2015).month(0).date(6).startOf('day').toDate();
// Week 2 Thursday
const expectedDate = moment().year(2015).month(0).date(8).startOf('day').toDate();
const nextInstanceOfDay = IC.getNextInstanceOfDay(4, startDate);
expect(nextInstanceOfDay).to.equalDate(expectedDate);
});
it('should return the next weekday occurence when in the week after when the same day', function() {
// Week 2 Tuesday
const startDate = moment().year(2015).month(0).date(6).startOf('day').toDate();
// Week 3 Tuesday
const expectedDate = moment().year(2015).month(0).date(13).startOf('day').toDate();
const nextInstanceOfDay = IC.getNextInstanceOfDay(2, startDate);
expect(nextInstanceOfDay).to.equalDate(expectedDate);
});
});
describe('calculateInstallmentAmount', function() {
it('should calculate amount per installment', function() {
const targetAmount = 500;
const numberOfInstallments = 10;
const amount = IC.calculateInstallmentAmount(targetAmount, numberOfInstallments);
expect(amount).to.equal(50);
});
it('should round down installmentAmount when decimal', function() {
const targetAmount = 499;
const numberOfInstallments = 10;
const amount = IC.calculateInstallmentAmount(targetAmount, numberOfInstallments);
expect(amount).to.equal(49);
});
});
describe('calculateLastInstallmentAmount', function() {
it('should calculate last Installment Amount', function() {
const targetAmount = 600;
const numberOfInstallments = 21;
const expectedLastInstallment = 40;
const lastInstallment = IC.calculateLastInstallmentAmount(targetAmount, numberOfInstallments);
expect(lastInstallment).to.equal(expectedLastInstallment);
});
});
describe('calculateInstallmentNumber', function() {
it('should calculate number of installments give targetAmount and installmentAmount', function() {
const targetAmount = 500;
const installmentAmount = 100;
const amount = IC.calculateInstallmentNumber(targetAmount, installmentAmount);
expect(amount).to.equal(5);
});
it('should round up number of installments when decimal', function() {
const targetAmount = 500;
const installmentAmount = 480;
const amount = IC.calculateInstallmentNumber(targetAmount, installmentAmount);
expect(amount).to.equal(2);
});
});
describe('installmentAmountsAreUnequal', function() {
it('should return true if installment amount is a float', function() {
const savingsTarget = 520;
const numberOfInstallments = 100;
const isUnequal = IC.installmentAmountsAreUnequal(savingsTarget, numberOfInstallments);
expect(isUnequal).to.equal(true);
});
it('should return false if installment amount is an integer', function() {
const savingsTarget = 500;
const numberOfInstallments = 100;
const isUnequal = IC.installmentAmountsAreUnequal(savingsTarget, numberOfInstallments);
expect(isUnequal).to.equal(false);
});
});