2020-07-15 16:26:41 +00:00
|
|
|
// License: LGPL-3.0-or-later
|
2021-02-25 18:28:03 +00:00
|
|
|
import BigNumber from 'bignumber.js';
|
2021-02-26 20:23:29 +00:00
|
|
|
import { Money, MoneyAsJson, Operand, RoundingMode } from './money';
|
2020-06-26 21:31:30 +00:00
|
|
|
|
|
|
|
describe("Money", () => {
|
2020-06-27 00:35:09 +00:00
|
|
|
describe('Money.fromCents', () => {
|
|
|
|
it('succeeds from a old Money object', () => {
|
|
|
|
expect.assertions(2);
|
|
|
|
const old = Money.fromCents(333, 'eur');
|
2020-06-26 21:31:30 +00:00
|
|
|
|
2020-06-27 00:35:09 +00:00
|
|
|
const result = Money.fromCents(old);
|
|
|
|
expect(result).toStrictEqual(old);
|
2020-06-26 21:31:30 +00:00
|
|
|
|
2020-06-27 00:35:09 +00:00
|
|
|
expect(result).not.toBe(old);
|
|
|
|
});
|
|
|
|
it('succeeds from a json', () => {
|
|
|
|
expect.hasAssertions();
|
2021-02-26 20:23:29 +00:00
|
|
|
const old:MoneyAsJson = { cents: 333, currency: 'eur' };
|
2020-06-26 21:31:30 +00:00
|
|
|
|
2020-06-27 00:35:09 +00:00
|
|
|
const result = Money.fromCents(old);
|
|
|
|
// eslint-disable-next-line jest/prefer-strict-equal
|
|
|
|
expect(result).toEqual(old);
|
2020-06-26 21:31:30 +00:00
|
|
|
|
2020-06-27 00:35:09 +00:00
|
|
|
expect(result).toBeInstanceOf(Money);
|
|
|
|
});
|
2020-06-26 21:31:30 +00:00
|
|
|
|
2020-09-14 17:25:15 +00:00
|
|
|
it('succeeds from a stringy json', () => {
|
|
|
|
expect.hasAssertions();
|
|
|
|
const old = Money.fromCents(333, 'eur');
|
|
|
|
|
2021-02-26 20:23:29 +00:00
|
|
|
const result = Money.fromCents({ cents: '333', currency: 'eur' });
|
2020-09-14 17:25:15 +00:00
|
|
|
// eslint-disable-next-line jest/prefer-strict-equal
|
|
|
|
expect(result).toEqual(old);
|
|
|
|
|
|
|
|
expect(result).toBeInstanceOf(Money);
|
|
|
|
});
|
|
|
|
|
2020-06-27 00:35:09 +00:00
|
|
|
it('succeeds from function parameters', () => {
|
|
|
|
expect.hasAssertions();
|
|
|
|
const result = Money.fromCents(333, 'eur');
|
|
|
|
// eslint-disable-next-line jest/prefer-strict-equal
|
2021-02-26 20:23:29 +00:00
|
|
|
expect(result).toEqual({ cents: 333, currency: 'eur' });
|
2020-06-26 21:31:30 +00:00
|
|
|
|
2020-06-27 00:35:09 +00:00
|
|
|
expect(result).toBeInstanceOf(Money);
|
|
|
|
});
|
2020-09-14 17:25:15 +00:00
|
|
|
|
|
|
|
it('succeeds from BigNumber', () => {
|
|
|
|
expect.hasAssertions();
|
|
|
|
const result = Money.fromCents(new BigNumber(333), 'eur');
|
|
|
|
// eslint-disable-next-line jest/prefer-strict-equal
|
2021-02-26 20:23:29 +00:00
|
|
|
expect(result).toEqual({ cents: 333, currency: 'eur' });
|
2020-09-14 17:25:15 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('rejects if string is not an integer', () => {
|
|
|
|
expect.hasAssertions();
|
|
|
|
expect(() => {
|
|
|
|
Money.fromCents('3344.4', 'usd');
|
|
|
|
}).toThrow(TypeError);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('rejects if BigNumber is not an integer', () => {
|
|
|
|
expect.hasAssertions();
|
|
|
|
expect(() => {
|
|
|
|
Money.fromCents(new BigNumber('3344.4'), 'usd');
|
|
|
|
}).toThrow(TypeError);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('rejects if number is not an integer', () => {
|
|
|
|
expect.hasAssertions();
|
|
|
|
expect(() => {
|
|
|
|
Money.fromCents(444.333, 'usd');
|
|
|
|
}).toThrow(TypeError);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
const cents1000 = Money.fromCents(1000, 'usd');
|
|
|
|
const cents500 = Money.fromCents(500, 'usd');
|
|
|
|
|
|
|
|
const euCents1000 = Money.fromCents(1000, 'eur');
|
|
|
|
|
|
|
|
const negative1000 = Money.fromCents(-1000, 'usd');
|
|
|
|
|
|
|
|
function verifyCurrency(func:(m:Money, other:Money) => unknown){
|
|
|
|
expect.assertions(1);
|
|
|
|
expect(() => func(cents1000, euCents1000)).toThrow(TypeError);
|
|
|
|
}
|
|
|
|
|
|
|
|
describe.each([
|
|
|
|
['add', (m:Money, other:Money) => m.add(other)],
|
|
|
|
['compare', (m:Money, other:Money) => m.compare(other)],
|
|
|
|
['divide', (m:Money, other:Money) => m.divide(other)],
|
|
|
|
['greaterThan', (m:Money, other:Money) => m.greaterThan(other)],
|
|
|
|
['greaterThanOrEqual', (m:Money, other:Money) => m.greaterThanOrEqual(other)],
|
|
|
|
['lessThan', (m:Money, other:Money) => m.lessThan(other)],
|
|
|
|
['lessThanOrEqual', (m:Money, other:Money) => m.lessThanOrEqual(other)],
|
|
|
|
['multiply', (m:Money, other:Money) => m.multiply(other)],
|
|
|
|
['subtract', (m:Money, other:Money) => m.subtract(other)],
|
|
|
|
|
|
|
|
])('.%s with %s', (_name, func) => {
|
|
|
|
|
|
|
|
it(`throw when currency doesn't match`, () => {
|
|
|
|
expect.assertions(1);
|
|
|
|
expect(() => func(cents1000, euCents1000)).toThrow(TypeError);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
describe.each([
|
|
|
|
['add', (m:Money, other:Operand) => m.add(other)],
|
|
|
|
['subtract', (m:Money, other:Operand) => m.subtract(other)],
|
|
|
|
])('.%s with %s', (_name, func) => {
|
|
|
|
|
|
|
|
it(`throw when other is a decimal number`, () => {
|
|
|
|
expect.assertions(1);
|
|
|
|
expect(() => func(cents1000, 4.5)).toThrow(TypeError);
|
|
|
|
});
|
|
|
|
|
|
|
|
it(`throw when other is a decimal BigNumber`, () => {
|
|
|
|
expect.assertions(1);
|
|
|
|
expect(() => func(cents1000, new BigNumber('4.5'))).toThrow(TypeError);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('.isZero', () => {
|
|
|
|
expect.assertions(1);
|
|
|
|
expect(cents1000.isZero()).toStrictEqual(false);
|
2020-06-27 00:35:09 +00:00
|
|
|
});
|
2020-09-14 17:25:15 +00:00
|
|
|
|
|
|
|
it('.isPositive', () => {
|
|
|
|
expect.assertions(1);
|
|
|
|
expect(cents1000.isPositive()).toStrictEqual(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('.isNegative', () => {
|
|
|
|
expect.assertions(1);
|
|
|
|
expect(negative1000.isNegative()).toStrictEqual(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('.compare', () => {
|
|
|
|
describe('greater', () => {
|
|
|
|
describe('Money', () => {
|
|
|
|
it('same currency', () => {
|
|
|
|
expect.assertions(1);
|
|
|
|
expect(cents1000.compare(cents500)).toStrictEqual(1);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('different currency', () => {
|
|
|
|
expect.assertions(1);
|
|
|
|
expect(() => {
|
|
|
|
cents1000.compare(euCents1000);
|
|
|
|
}).toThrow(TypeError);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('BigNumber', () => {
|
|
|
|
it('same currency', () => {
|
|
|
|
expect.assertions(1);
|
|
|
|
expect(cents1000.compare(cents500)).toStrictEqual(1);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('different currency', () => {
|
|
|
|
expect.assertions(1);
|
|
|
|
expect(() => {
|
|
|
|
cents1000.compare(euCents1000);
|
|
|
|
}).toThrow(TypeError);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('.divide', () => {
|
|
|
|
it('divides 36 into 9', () => {
|
|
|
|
expect.assertions(1);
|
2021-02-26 20:23:29 +00:00
|
|
|
expect(Money.fromCents(36, 'usd').divide(9).toJSON()).toStrictEqual({cents: 4, currency: 'usd'});
|
2020-09-14 17:25:15 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('throws if the currencies do not match', () => {
|
|
|
|
expect.assertions(1);
|
|
|
|
verifyCurrency((m, other) => m.divide(other));
|
|
|
|
});
|
|
|
|
|
|
|
|
it('defaults to rounding to HalfUp', () => {
|
|
|
|
expect.assertions(3);
|
2021-02-26 20:23:29 +00:00
|
|
|
expect(Money.fromCents(40, 'usd').divide(Money.fromCents(9, 'usd')).toJSON()).toStrictEqual({cents: 4, currency: 'usd'});
|
2020-09-14 17:25:15 +00:00
|
|
|
|
2021-02-26 20:23:29 +00:00
|
|
|
expect(Money.fromCents(41, 'usd').divide(Money.fromCents(9, 'usd')).toJSON()).toStrictEqual({cents: 5, currency: 'usd'});
|
2020-09-14 17:25:15 +00:00
|
|
|
|
2021-02-26 20:23:29 +00:00
|
|
|
expect(Money.fromCents(7, 'usd').divide(Money.fromCents(2, 'usd')).toJSON()).toStrictEqual({cents: 4, currency: 'usd'});
|
2020-09-14 17:25:15 +00:00
|
|
|
});
|
|
|
|
it('rounds to floor if requested', () => {
|
|
|
|
expect.assertions(1);
|
2021-02-26 20:23:29 +00:00
|
|
|
expect(Money.fromCents(41, 'usd').divide(Money.fromCents(9, 'usd'), RoundingMode.Floor).toJSON()).toStrictEqual({cents: 4, currency: 'usd'});
|
2020-09-14 17:25:15 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('rounds to ceil if requested', () => {
|
|
|
|
expect.assertions(1);
|
2021-02-26 20:23:29 +00:00
|
|
|
expect(Money.fromCents(40, 'usd').divide(Money.fromCents(9, 'usd'), RoundingMode.Ceil).toJSON()).toStrictEqual({cents: 5, currency: 'usd'});
|
2020-09-14 17:25:15 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('.multiply', () => {
|
|
|
|
it('multiply 9 x 4', () => {
|
|
|
|
expect.assertions(1);
|
2021-02-26 20:23:29 +00:00
|
|
|
expect(Money.fromCents(9, 'usd').multiply(4).toJSON()).toStrictEqual({cents: 36, currency: 'usd'});
|
2020-09-14 17:25:15 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('throws if the currencies do not match', () => {
|
|
|
|
expect.assertions(1);
|
|
|
|
verifyCurrency((m, other) => m.multiply(other));
|
|
|
|
});
|
|
|
|
|
|
|
|
it('handles multiplying by a decimal properly', () => {
|
|
|
|
expect.assertions(1);
|
2021-02-26 20:23:29 +00:00
|
|
|
expect(Money.fromCents('3', 'usd').multiply(new BigNumber('1.263')).toJSON()).toStrictEqual({cents: 4, currency: 'usd'});
|
2020-09-14 17:25:15 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('defaults to rounding to HalfUp', () => {
|
|
|
|
expect.assertions(1);
|
2021-02-26 20:23:29 +00:00
|
|
|
expect(Money.fromCents(7, 'usd').multiply(new BigNumber('.5')).toJSON()).toStrictEqual({cents: 4, currency: 'usd'});
|
2020-09-14 17:25:15 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('rounds to floor if requested', () => {
|
|
|
|
expect.assertions(1);
|
2021-02-26 20:23:29 +00:00
|
|
|
expect(Money.fromCents('3', 'usd').multiply('1.263', RoundingMode.Floor).toJSON()).toStrictEqual({cents: 3, currency: 'usd'});
|
2020-09-14 17:25:15 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('rounds to ceil if requested', () => {
|
|
|
|
expect.assertions(1);
|
2021-02-26 20:23:29 +00:00
|
|
|
expect(Money.fromCents('3', 'usd').multiply('1.263', RoundingMode.Ceil).toJSON()).toStrictEqual({cents: 4, currency: 'usd'});
|
2020-09-14 17:25:15 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('.toBigNumber', () => {
|
|
|
|
it('doesnt round to nearest integer', () => {
|
|
|
|
expect.assertions(1);
|
|
|
|
expect(cents1000.toBigNumber().plus('1.2').toString()).toStrictEqual('1001.2');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-06-27 00:22:45 +00:00
|
|
|
});
|