UNPKG

money-lib

Version:

TypeScript library to work with money

544 lines (494 loc) 13.5 kB
import assert from "node:assert"; import { describe, test, expect } from "bun:test"; import { setupMoney, money } from "../v2"; import { defaultConfig } from "../lib/config"; describe("v2", () => { test("different initializers", () => { // Any of these works: money(100); money("€100", "EUR"); money("$100.99"); money("€ 100"); money("100eur"); money("100 btc"); // with cents money("100cents"); money("100 cents"); money("€100cents"); money("€ 100 cents "); money("100 EUR cents"); money("100EURcents"); money("100 cents EUR"); money("100 cents", "EUR"); const m = money("100 eur").add("€57.99").sub(7.99).mul(5.56399); expect(m.fmt()).toBe("€834,60"); expect(m.float()).toBe(834.6); expect(m.cents()).toBe(83460); expect(money().fmt()).toBe("€0,00"); expect(money({ cents: 50, currency: "EUR" }).fmt()).toBe("€0,50"); expect(money({ decimal: 5.45, currency: "EUR" }).fmt()).toBe("€5,45"); // must not compile: // money("🎃 15"); // money("15 spooky"); // money("200uah"); }); describe("basic use cased", () => { test("should do arithm and fmt money", () => { const m = money(0) .add({ amount: 4499, currency: "EUR" }) .sub({ amount: 299, currency: "EUR" }) .mul(5.56399) .div(5.56399) .fmt(); assert.strictEqual(m, "€42,00"); }); test("should do arithm and fmt money with default currency", () => { const m = money(0) .add({ amount: 4499 }) .sub({ amount: 299 }) .mul(5.56399) .div(5.56399) .fmt(); assert.strictEqual(m, "€42,00"); }); }); describe("serialization", () => { test("int", () => { assert.equal(money(100.42).cents(), 10042); }); test("float / number", () => { assert.equal(money(100.42).float(), 100.42); assert.equal(money(100.42).number(), 100.42); }); test("centsStr", () => { assert.equal(money(100.42).centStr(), "10042"); assert.equal(money(0).centStr(), "0"); assert.equal(money(0.01).centStr(), "1"); }); test("string", () => { assert.equal(money(100.42).string(), "100.42"); assert.equal(money(0.01).string(), "0.01"); assert.equal(money(0).string(), "0.00"); }); }); describe("floatToInt intToFloat", () => { test("floatToInt", () => { assert.equal(money(100.42).int(), 10042); }); test("intToFloat", () => { assert.equal(money("100.42").float(), 100.42); }); }); describe("arithmetics", () => { test("add", () => { assert.ok( Bun.deepEquals(money(100.42).add(100.42).json(), { currency: "EUR", amount: 20084, }) ); }); test("add many", () => { const foo = money(0.01); const bar = money("0.01eur"); assert.equal( money("0.01") .add("0.02", { amount: 3 }, foo, "0.02", money("0.01"), money(0.01)) .number(), 0.11 ); }); test("sub", () => { assert.ok( Bun.deepEquals(money("100.42").sub(100.42).json(), { currency: "EUR", amount: 0, }) ); assert.ok( Bun.deepEquals(money("1").sub({ currency: "EUR", amount: 50 }).json(), { currency: "EUR", amount: 50, }) ); }); test("sub many", () => { assert.ok( Bun.deepEquals( money("0.06").sub({ amount: 3 }, 0.02, money(0.01)).json(), { currency: "EUR", amount: 0 } ) ); }); test("mul", () => { assert.ok( Bun.deepEquals(money(100.42).mul(2).json(), { currency: "EUR", amount: 20084, }) ); }); test("div", () => { assert.ok( Bun.deepEquals(money(100.42).div(2).json(), { currency: "EUR", amount: 5021, }) ); assert.ok( Bun.deepEquals(money(70.44).div(100).json(), { currency: "EUR", amount: 70, }) ); }); test("abs", () => { assert.equal(money(100.42).abs().fmt(), "€100,42"); assert.equal(money(-100.42).abs().fmt(), "€100,42"); }); }); describe("comparison", () => { test("equal", () => { assert.strictEqual( money(100.42).eq({ currency: "EUR", amount: 10042, }), true ); assert.strictEqual( money(100.42).eq({ currency: "EUR", amount: 10043, }), false ); assert.strictEqual(money(100.42).isNeg(), false); assert.strictEqual(money(-100.42).isNeg(), true); }); test("lt", () => { assert.strictEqual( money(100.42).lt({ currency: "EUR", amount: 10043, }), true ); assert.strictEqual( money(100.42).lt({ currency: "EUR", amount: 10041, }), false ); assert.strictEqual( money(100.42).lt({ currency: "EUR", amount: 10042, }), false ); }); test("lte", () => { assert.strictEqual( money(100.42).lte({ currency: "EUR", amount: 10042, }), true ); assert.strictEqual( money(100.41).lte({ currency: "EUR", amount: 10043, }), true ); assert.strictEqual( money(100.42).lte({ currency: "EUR", amount: 10041, }), false ); }); test("gt", () => { assert.strictEqual( money(100.42).gt({ currency: "EUR", amount: 10042, }), false ); assert.strictEqual( money(100.42).gt({ currency: "EUR", amount: 10041, }), true ); assert.strictEqual( money(100.42).gt({ currency: "EUR", amount: 10043, }), false ); }); test("gte", () => { assert.strictEqual( money(100.42).gte({ currency: "EUR", amount: 10042, }), true ); assert.strictEqual( money(100.42).gte({ currency: "EUR", amount: 10041, }), true ); assert.strictEqual( money(100.42).gte({ currency: "EUR", amount: 10043, }), false ); }); test("cmp", () => { assert.strictEqual( money(100.42).cmp({ currency: "EUR", amount: 10042, }), 0 ); assert.strictEqual(money(100.42).cmp(money(100.41)), 1); assert.strictEqual( money(100.42).cmp({ currency: "EUR", amount: 10043, }), -1 ); }); test("min", () => { const m1 = money(0.01); const m2 = money(0); const m3 = money(0.02); const m4 = money(-0.01); assert.ok( Bun.deepEquals(money(0).min(m1, m2, m3, m4).json(), { currency: "EUR", amount: -1, }) ); assert.ok( Bun.deepEquals(money(0).min(m1, m2, m3, { amount: -2 }, m4).json(), { currency: "EUR", amount: -2, }) ); assert.ok( Bun.deepEquals(money(0).min(m1, m2).json(), { currency: "EUR", amount: 0, }) ); assert.ok( Bun.deepEquals(money(0).min(m1).json(), { currency: "EUR", amount: 1, }) ); }); test("max", () => { const m1 = money(0.01); const m2 = money(0); const m3 = money(0.02); const m4 = money(-0.01); assert.ok( Bun.deepEquals(money(0).max(m1, m2, m3, m4).json(), { currency: "EUR", amount: 2, }) ); assert.ok( Bun.deepEquals(money(0).max(m1, m2, m3, { amount: 3 }, m4).json(), { currency: "EUR", amount: 3, }) ); assert.ok( Bun.deepEquals(money(0).max(m1, m2).json(), { currency: "EUR", amount: 1, }) ); assert.ok( Bun.deepEquals(money(0).max(m1).json(), { currency: "EUR", amount: 1, }) ); }); }); describe("formatting", () => { test("fmt", () => { assert.equal(money(0).fmt(), "€0,00"); assert.equal(money(0.05).fmt(), "€0,05"); assert.equal(money(0.5).fmt(), "€0,50"); assert.equal(money(1000.42).fmt(), "€1.000,42"); assert.equal( money(1000.42).fmt({ cents: false, }), "€1.000,42" ); assert.equal( money(1000).fmt({ cents: false, }), "€1.000" ); assert.equal( money(0.5).fmt({ cents: false, }), "€0,50" ); assert.equal( money(0).fmt({ cents: false, }), "€0" ); assert.equal( money(0).fmt({ cents: true, }), "€0,00" ); // assert.equal( // money(0).fmt({ // locale: "IE", // }), // "€1,000.42" // ); assert.equal(money(0.01).fmt(), "€0,01"); }); test("fmt negative amount", () => { assert.ok(Bun.deepEquals(money(-1000.42).fmt(), "-€1.000,42")); }); test("fmts", () => { assert.ok( Bun.deepEquals(money(1000555.42).fmts(), { cents: "42", currencySymbol: "€", decimalSeparator: ",", base: "1000555", baseFormatted: "1.000.555", sign: "+", }) ); assert.ok( Bun.deepEquals(money(-1000555.42).fmts(), { cents: "42", currencySymbol: "€", decimalSeparator: ",", base: "1000555", baseFormatted: "1.000.555", sign: "-", }) ); }); test("fmt BTC", () => { assert.equal(money("0 BTC").fmt(), "₿0,00000000"); assert.equal(money("0.00000005 BTC").fmt(), "₿0,00000005"); assert.equal(money("0.0000005 BTC").fmt(), "₿0,00000050"); assert.equal(money("0.00000500 BTC").fmt({}), "₿0,00000500"); assert.equal( money("0.000005 BTC").fmt({ trailingZeros: false }), "₿0,000005" ); assert.equal(money("1 BTC").fmt(), "₿1,00000000"); assert.equal(money(" 1 BTC").fmt({ cents: false }), "₿1"); assert.equal(money("₿199").fmt({ cents: false }), "₿199"); assert.equal(money("1999.00000005 BTC").fmt(), "₿1.999,00000005"); assert.equal(money("1999.00000005 BTC").fmt(), "₿1.999,00000005"); }); test("fmt withPlusSign", () => { assert.equal(money("1 EUR").fmt(), "€1,00"); assert.equal(money("1 EUR").fmt({ withPlusSign: true }), "+€1,00"); assert.equal(money("0 EUR").fmt({ withPlusSign: true }), "€0,00"); assert.equal(money("-1 EUR").fmt({ withPlusSign: true }), "-€1,00"); }); }); describe("validation", () => {}); describe("transformation", () => {}); describe("parsings", () => { test("works the same as initializer but with wider string type", () => { expect(money().parse("€100").fmt()).toBe("€100,00"); expect(money().parse("100.45", "EUR").fmt()).toBe("€100,45"); expect(money().parse("100", "EUR").fmt()).toBe("€100,00"); expect(money().parse("100 eur").fmt()).toBe("€100,00"); expect(money().parse("€ 100").fmt()).toBe("€100,00"); expect(money().parse("100,45").fmt()).toBe("€100,45"); // comma treated as decimal separator expect(money(0).parse("10.500,99", "EUR").fmt()).toBe("€10,50"); // thousand separators are ignored expect(money(0).parse("10500.99", "EUR").fmt()).toBe("€10.500,99"); }); test("parses to 0 as fallback", () => { expect(money().parse("xxx").fmt()).toBe("€0,00"); expect(money().parse("foo", "USD").fmt()).toBe("$0,00"); expect(money().parse("").fmt()).toBe("€0,00"); }); test("EUR", () => { const expected = { currency: "EUR", amount: 1050099, }; assert.ok( Bun.deepEquals(money(0).parse("10500,99", "EUR").json(), expected) ); assert.ok( Bun.deepEquals(money(0).parse("10_500 , 99", "EUR").json(), expected) ); }); }); describe("custom config", () => { test("custom config", () => { const { money: moneyCustom } = setupMoney({ currencies: [ { code: "EUR" as const, symbol: "€" as const, scale: 2, }, { code: "BTC" as const, symbol: "₿" as const, scale: 8, }, { code: "SPOOKY" as const, symbol: "🎃" as const, scale: 5, }, ], defaultCurrency: "EUR" as const, defaultRoundingMethod: "bankers", }); expect(moneyCustom("-10.61eur").fmt()).toBe("-€10,61"); expect(moneyCustom("🎃 -10.61").fmt()).toBe("-🎃10,61000"); expect(moneyCustom("0.15 spooky").fmt({ trailingZeros: false })).toBe( "🎃0,15" ); // must not compile // assert.equal(moneyCustom("-10.61pund").fmt(), "-€10,61000"); setupMoney(defaultConfig); }); }); });