money-lib
Version:
TypeScript library to work with money
792 lines (747 loc) • 19.9 kB
text/typescript
import assert from "node:assert";
import { describe, expect, it, test } from "bun:test";
import money from "../index";
describe("chained", () => {
describe("basic use cased", () => {
test("should do arithm and format money", () => {
const m = money()
.add({ amount: 4499, currency: "EUR" })
.subtract({ amount: 299, currency: "EUR" })
.multiply(5.56399)
.divide(5.56399)
.format();
assert.strictEqual(m, "€42,00");
});
test("should do arithm and format money with default currency", () => {
const m = money()
.add({ amount: 4499 })
.subtract({ amount: 299 })
.multiply(5.56399)
.divide(5.56399)
.format();
assert.strictEqual(m, "€42,00");
});
});
describe("initialization", () => {
test("zero", () => {
assert.ok(
Bun.deepEquals(money().zero().toJSON(), { currency: "EUR", amount: 0 })
);
});
test("fromInt", () => {
assert.ok(
Bun.deepEquals(money().fromInt(10042).toJSON(), {
currency: "EUR",
amount: 10042,
})
);
});
test("fromFloat", () => {
assert.ok(
Bun.deepEquals(money().fromFloat(100.42).toJSON(), {
currency: "EUR",
amount: 10042,
})
);
assert.ok(
Bun.deepEquals(money().fromFloat(100).toJSON(), {
currency: "EUR",
amount: 10000,
})
);
assert.ok(
Bun.deepEquals(money().fromFloat(0.025).toJSON(), {
currency: "EUR",
amount: 2, // bankers rounding applied
})
);
});
test("fromFloatString", () => {
assert.ok(
Bun.deepEquals(money().fromFloatString("100.42").toJSON(), {
currency: "EUR",
amount: 10042,
})
);
assert.ok(
Bun.deepEquals(money().fromFloatString("100").toJSON(), {
currency: "EUR",
amount: 10000,
})
);
assert.ok(
Bun.deepEquals(money().fromFloatString("100.42").toJSON(), {
currency: "EUR",
amount: 10042,
})
);
assert.ok(
Bun.deepEquals(money().fromFloatString("0").toJSON(), {
currency: "EUR",
amount: 0,
})
);
assert.ok(
Bun.deepEquals(money().fromFloatString("1").toJSON(), {
currency: "EUR",
amount: 100,
})
);
assert.ok(
Bun.deepEquals(money().fromFloatString("0.01").toJSON(), {
currency: "EUR",
amount: 1,
})
);
assert.ok(
Bun.deepEquals(money().fromFloatString("0.001").toJSON(), {
currency: "EUR",
amount: 0,
})
);
assert.ok(
Bun.deepEquals(money().fromFloatString("-100.42").toJSON(), {
currency: "EUR",
amount: -10042,
})
);
assert.ok(
Bun.deepEquals(money().fromFloatString("-1").toJSON(), {
currency: "EUR",
amount: -100,
})
);
assert.ok(
Bun.deepEquals(money().fromFloatString("-0.01").toJSON(), {
currency: "EUR",
amount: -1,
})
);
assert.ok(
Bun.deepEquals(money().fromFloatString("-0").toJSON(), {
currency: "EUR",
amount: 0,
})
);
assert.ok(
Bun.deepEquals(money().fromFloatString("x").toJSON(), {
currency: "EUR",
amount: 0,
})
);
assert.ok(
Bun.deepEquals(
money().fromFloatString("216.6666666666666667").toJSON(),
{
currency: "EUR",
amount: 21667,
}
)
);
});
test("fromIntString", () => {
assert.ok(
Bun.deepEquals(money().fromIntString("10042").toJSON(), {
currency: "EUR",
amount: 10042,
})
);
assert.ok(
Bun.deepEquals(money().fromIntString("100").toJSON(), {
currency: "EUR",
amount: 100,
})
);
assert.ok(
Bun.deepEquals(money().fromIntString("100.42").toJSON(), {
currency: "EUR",
amount: 100,
})
);
assert.ok(
Bun.deepEquals(money().fromIntString("0").toJSON(), {
currency: "EUR",
amount: 0,
})
);
assert.ok(
Bun.deepEquals(money().fromIntString("1").toJSON(), {
currency: "EUR",
amount: 1,
})
);
assert.ok(
Bun.deepEquals(money().fromIntString("0.01").toJSON(), {
currency: "EUR",
amount: 0,
})
);
assert.ok(
Bun.deepEquals(money().fromIntString("0.001").toJSON(), {
currency: "EUR",
amount: 0,
})
);
assert.ok(
Bun.deepEquals(money().fromIntString("-100.42").toJSON(), {
currency: "EUR",
amount: -100,
})
);
assert.ok(
Bun.deepEquals(money().fromIntString("-1").toJSON(), {
currency: "EUR",
amount: -1,
})
);
assert.equal(money().fromIntString("-0.01").toJSON().amount, 0);
assert.equal(money().fromIntString("-0").toJSON().amount, 0);
assert.ok(
Bun.deepEquals(money().fromIntString("x").toJSON(), {
currency: "EUR",
amount: 0,
})
);
});
});
describe("serialization", () => {
test("toInt", () => {
assert.equal(money({ currency: "EUR", amount: 10042 }).toInt(), 10042);
});
test("toFloat", () => {
assert.equal(money({ currency: "EUR", amount: 10042 }).toFloat(), 100.42);
});
test("toString", () => {
assert.equal(
money({ currency: "EUR", amount: 10042 }).toString(),
"10042"
);
assert.equal(money({ currency: "EUR", amount: 0 }).toString(), "0");
assert.equal(money({ currency: "EUR", amount: 1 }).toString(), "1");
});
test("toFloatString", () => {
assert.equal(
money({ currency: "EUR", amount: 10042 }).toFloatString(),
"100.42"
);
assert.equal(
money({ currency: "EUR", amount: 1 }).toFloatString(),
"0.01"
);
assert.equal(
money({ currency: "EUR", amount: 0 }).toFloatString(),
"0.00"
);
});
});
describe("floatToInt intToFloat", () => {
test("floatToInt", () => {
assert.equal(money().fromFloat(100.42).toInt(), 10042);
});
test("intToFloat", () => {
assert.equal(money().fromInt(10042).toFloat(), 100.42);
});
});
describe("arithmetics", () => {
test("add", () => {
assert.ok(
Bun.deepEquals(
money({ currency: "EUR", amount: 10042 })
.add({ currency: "EUR", amount: 10042 })
.toJSON(),
{ currency: "EUR", amount: 20084 }
)
);
});
test("add many ", () => {
assert.ok(
Bun.deepEquals(
money({ amount: 1 }).add({ amount: 2 }, { amount: 3 }).toJSON(),
{ currency: "EUR", amount: 6 }
)
);
});
test("subtract", () => {
assert.ok(
Bun.deepEquals(
money({ currency: "EUR", amount: 10042 })
.subtract({ currency: "EUR", amount: 10042 })
.toJSON(),
{ currency: "EUR", amount: 0 }
)
);
assert.ok(
Bun.deepEquals(
money({ currency: "EUR", amount: 100 })
.subtract({ currency: "EUR", amount: 50 })
.toJSON(),
{ currency: "EUR", amount: 50 }
)
);
});
test("subtract many", () => {
assert.ok(
Bun.deepEquals(
money({ amount: 6 })
.subtract({ amount: 3 }, { amount: 2 }, { amount: 1 })
.toJSON(),
{ currency: "EUR", amount: 0 }
)
);
});
test("multiply", () => {
assert.ok(
Bun.deepEquals(
money({ currency: "EUR", amount: 10042 }).multiply(2).toJSON(),
{ currency: "EUR", amount: 20084 }
)
);
});
test("divide", () => {
assert.ok(
Bun.deepEquals(
money({ currency: "EUR", amount: 10042 }).divide(2).toJSON(),
{ currency: "EUR", amount: 5021 }
)
);
assert.ok(
Bun.deepEquals(
money({ currency: "EUR", amount: 7044 }).divide(100).toJSON(),
{ currency: "EUR", amount: 70 }
)
);
});
test("abs", () => {
assert.equal(
money({ currency: "EUR", amount: 10042 }).abs().format(),
"€100,42"
);
assert.equal(
money({ currency: "EUR", amount: -10042 }).abs().format(),
"€100,42"
);
});
});
describe("comparison", () => {
test("equal", () => {
assert.strictEqual(
money({ currency: "EUR", amount: 10042 }).equals({
currency: "EUR",
amount: 10042,
}),
true
);
assert.strictEqual(
money({ currency: "EUR", amount: 10042 }).equals({
currency: "EUR",
amount: 10043,
}),
false
);
assert.strictEqual(
money({ currency: "EUR", amount: 10042 }).isNegative(),
false
);
assert.strictEqual(
money({ currency: "EUR", amount: -10042 }).isNegative(),
true
);
});
test("lessThan", () => {
assert.strictEqual(
money({ currency: "EUR", amount: 10042 }).lessThan({
currency: "EUR",
amount: 10043,
}),
true
);
assert.strictEqual(
money({ currency: "EUR", amount: 10042 }).lessThan({
currency: "EUR",
amount: 10041,
}),
false
);
assert.strictEqual(
money({ currency: "EUR", amount: 10042 }).lessThan({
currency: "EUR",
amount: 10042,
}),
false
);
});
test("lessThanOrEqual", () => {
assert.strictEqual(
money({ currency: "EUR", amount: 10042 }).lessThanOrEqual({
currency: "EUR",
amount: 10042,
}),
true
);
assert.strictEqual(
money({ currency: "EUR", amount: 10041 }).lessThanOrEqual({
currency: "EUR",
amount: 10043,
}),
true
);
assert.strictEqual(
money({ currency: "EUR", amount: 10042 }).lessThanOrEqual({
currency: "EUR",
amount: 10041,
}),
false
);
});
test("greaterThan", () => {
assert.strictEqual(
money({ currency: "EUR", amount: 10042 }).greaterThan({
currency: "EUR",
amount: 10042,
}),
false
);
assert.strictEqual(
money({ currency: "EUR", amount: 10042 }).greaterThan({
currency: "EUR",
amount: 10041,
}),
true
);
assert.strictEqual(
money({ currency: "EUR", amount: 10042 }).greaterThan({
currency: "EUR",
amount: 10043,
}),
false
);
});
test("greaterThanOrEqual", () => {
assert.strictEqual(
money({ currency: "EUR", amount: 10042 }).greaterThanOrEqual({
currency: "EUR",
amount: 10042,
}),
true
);
assert.strictEqual(
money({ currency: "EUR", amount: 10042 }).greaterThanOrEqual({
currency: "EUR",
amount: 10041,
}),
true
);
assert.strictEqual(
money({ currency: "EUR", amount: 10042 }).greaterThanOrEqual({
currency: "EUR",
amount: 10043,
}),
false
);
});
test("compare", () => {
assert.strictEqual(
money({ currency: "EUR", amount: 10042 }).compare({
currency: "EUR",
amount: 10042,
}),
0
);
assert.strictEqual(
money({ currency: "EUR", amount: 10042 }).compare({
currency: "EUR",
amount: 10041,
}),
1
);
assert.strictEqual(
money({ currency: "EUR", amount: 10042 }).compare({
currency: "EUR",
amount: 10043,
}),
-1
);
});
test("min", () => {
const m1 = money({ amount: 1 });
const m2 = money({ amount: 0 });
const m3 = money({ amount: 2 });
const m4 = money({ amount: -1 });
assert.ok(
Bun.deepEquals(money().min(m1, m2, m3, m4).toJSON(), {
currency: "EUR",
amount: -1,
})
);
assert.ok(
Bun.deepEquals(money().min(m1, m2, m3, { amount: -2 }, m4).toJSON(), {
currency: "EUR",
amount: -2,
})
);
assert.ok(
Bun.deepEquals(money().min(m1, m2).toJSON(), {
currency: "EUR",
amount: 0,
})
);
assert.ok(
Bun.deepEquals(money().min(m1).toJSON(), {
currency: "EUR",
amount: 1,
})
);
});
test("max", () => {
const m1 = money({ amount: 1 });
const m2 = money({ amount: 0 });
const m3 = money({ amount: 2 });
const m4 = money({ amount: -1 });
assert.ok(
Bun.deepEquals(money().max(m1, m2, m3, m4).toJSON(), {
currency: "EUR",
amount: 2,
})
);
assert.ok(
Bun.deepEquals(money().max(m1, m2, m3, { amount: 3 }, m4).toJSON(), {
currency: "EUR",
amount: 3,
})
);
assert.ok(
Bun.deepEquals(money().max(m1, m2).toJSON(), {
currency: "EUR",
amount: 1,
})
);
assert.ok(
Bun.deepEquals(money().max(m1).toJSON(), {
currency: "EUR",
amount: 1,
})
);
});
});
describe("formatting", () => {
test("format", () => {
assert.equal(money({ currency: "EUR", amount: 0 }).format(), "€0,00");
assert.equal(money({ currency: "EUR", amount: 5 }).format(), "€0,05");
assert.equal(money({ currency: "EUR", amount: 50 }).format(), "€0,50");
assert.equal(
money({ currency: "EUR", amount: 100042 }).format(),
"€1.000,42"
);
assert.equal(
money({ currency: "EUR", amount: 100042 }).format({
cents: false,
}),
"€1.000,42"
);
assert.equal(
money({ currency: "EUR", amount: 100042 }).format({
cents: "ifAny",
}),
"€1.000,42"
);
assert.equal(
money({ currency: "EUR", amount: 100000 }).format({
cents: false,
}),
"€1.000"
);
assert.equal(
money({ currency: "EUR", amount: 100000 }).format({
cents: "ifAny",
}),
"€1.000"
);
assert.equal(
money({ currency: "EUR", amount: 50 }).format({
cents: false,
}),
"€0,50"
);
assert.equal(
money({ currency: "EUR", amount: 0 }).format({
cents: false,
}),
"€0"
);
assert.equal(
money({ currency: "EUR", amount: 0 }).format({
cents: true,
}),
"€0,00"
);
assert.equal(
money({ currency: "EUR", amount: 100042 }).format({
locale: "IE",
}),
"€1,000.42"
);
assert.equal(money().fromFloat(0.01).format(), "€0,01");
assert.equal(
money({ currency: "EUR", amount: 100042 }).format({
cents: "no",
}),
"€1.000"
);
});
test("format negative amount", () => {
assert.ok(
Bun.deepEquals(
money({ currency: "EUR", amount: -100042 }).format(),
"-€1.000,42"
)
);
});
test("formatParts", () => {
assert.ok(
Bun.deepEquals(
money({ currency: "EUR", amount: 100055542 }).formatParts(),
{
cents: "42",
currencySymbol: "€",
decimalSeparator: ",",
whole: "1000555",
wholeFormatted: "1.000.555",
sign: "+",
}
)
);
assert.ok(
Bun.deepEquals(
money({ currency: "EUR", amount: -100055542 }).formatParts(),
{
cents: "42",
currencySymbol: "€",
decimalSeparator: ",",
whole: "1000555",
wholeFormatted: "1.000.555",
sign: "-",
}
)
);
});
test("format BTC", () => {
assert.equal(
money({ currency: "BTC", amount: 0 }).format(),
"₿0,00000000"
);
assert.equal(
money({ currency: "BTC", amount: 5 }).format(),
"₿0,00000005"
);
assert.equal(
money({ currency: "BTC", amount: 50 }).format(),
"₿0,00000050"
);
assert.equal(
money({ currency: "BTC", amount: 500 }).format({}),
"₿0,00000500"
);
assert.equal(
money({ currency: "BTC", amount: 500 }).format({
trailingZeros: false,
}),
"₿0,000005"
);
assert.equal(
money({ currency: "BTC", amount: 100000000 }).format(),
"₿1,00000000"
);
assert.equal(
money({ currency: "BTC", amount: 100000000 }).format({
cents: false,
}),
"₿1"
);
assert.equal(
money({ currency: "BTC", amount: 19900000000 }).format({
cents: false,
}),
"₿199"
);
assert.equal(
money({ currency: "BTC", amount: 199900000005 }).format(),
"₿1.999,00000005"
);
assert.equal(
money({ currency: "BTC", amount: 199900000005 }).format(),
"₿1.999,00000005"
);
});
test("format withPlusSign", () => {
assert.equal(money({ currency: "EUR", amount: 100 }).format(), "€1,00");
assert.equal(
money({ currency: "EUR", amount: 100 }).format({ withPlusSign: true }),
"+€1,00"
);
assert.equal(
money({ currency: "EUR", amount: 0 }).format({ withPlusSign: true }),
"€0,00"
);
assert.equal(
money({ currency: "EUR", amount: -100 }).format({ withPlusSign: true }),
"-€1,00"
);
});
});
describe("validation", () => {});
describe("transformation", () => {});
describe("parsings", () => {
test("EUR", () => {
const expected = {
currency: "EUR",
amount: 1050099,
};
assert.ok(
Bun.deepEquals(money().parse("10.500,99", "EUR").toJSON(), expected)
);
assert.ok(
Bun.deepEquals(money().parse("10500,99", "EUR").toJSON(), expected)
);
assert.ok(
Bun.deepEquals(money().parse("10_500 , 99", "EUR").toJSON(), expected)
);
assert.notDeepEqual(money().parse("10500.99", "EUR").toJSON(), expected);
});
test("explicit decimal separator", () => {
const expected = {
currency: "EUR",
amount: 1050099,
};
assert.ok(
Bun.deepEquals(
money().parse("10,500.99", "EUR", undefined, ".").toJSON(),
expected
)
);
assert.ok(
Bun.deepEquals(
money().parse("10500.99", "EUR", undefined, ".").toJSON(),
expected
)
);
assert.ok(
Bun.deepEquals(
money().parse("10_500 . 99", "EUR", undefined, ".").toJSON(),
expected
)
);
assert.notDeepEqual(
money().parse("10.500,99", "EUR", undefined, ".").toJSON(),
expected
);
});
});
describe("unknown currency", () => {
it("should no throw and fallback to default currency", () => {
Bun.deepEquals(money().fromFloat(15.45, "XXX").toJSON(), {
currency: "EUR",
amount: 1545,
});
});
});
});