import { test } from "node:test"; import assert from "node:assert/strict"; import { add, compare, divPow10, mul, mulByBigInt, parseDecimal, round, toFixed, toString, } from "../src/money.js"; const d = parseDecimal; test("0.1 + 0.2 = 0.3", () => { assert.equal(toString(add(d("0.1"), d("0.2"))), "0.3"); }); test("мелкая цена × много токенов без потери точности", () => { assert.equal(toString(mulByBigInt(d("0.00000012"), 50_000_000n)), "6"); assert.equal(toString(mulByBigInt(d("0.0000001289925"), 123_456_789n)), "15.9249998550825"); // цена за 1M токенов assert.equal(toString(divPow10(d("79.91392973"), 6)), "0.00007991392973"); assert.equal(toString(mul(d("1.5"), d("0.25"))), "0.375"); assert.equal(toString(mul(d("-1.5"), d("0.2"))), "-0.3"); }); test("round HALF UP — от нуля на .5", () => { assert.equal(toString(round(d("0.125"), 2)), "0.13"); assert.equal(toString(round(d("-0.125"), 2)), "-0.13"); assert.equal(toString(round(d("0.124999"), 2)), "0.12"); assert.equal(toString(round(d("2.5"), 0)), "3"); assert.equal(toString(round(d("-2.5"), 0)), "-3"); assert.equal(toString(round(d("0.0005"), 3)), "0.001"); assert.equal(toString(round(d("-0.0004"), 3)), "0"); assert.equal(toFixed(d("1.005"), 2), "1.01"); assert.equal(toFixed(d("7"), 2), "7.00"); assert.equal(toFixed(d("-0.001"), 2), "0.00"); }); test("parseDecimal строгий", () => { assert.throws(() => parseDecimal(0.1), TypeError); for (const bad of ["1e-7", "", "1,5", " 1", "1.", ".5", "+1", "--1", "NaN"]) { assert.throws(() => parseDecimal(bad), SyntaxError, bad); } assert.equal(toString(d("-12.3400")), "-12.34"); }); test("compare и канонический toString для нулей и отрицательных", () => { assert.equal(compare(d("0"), d("0.0")), 0); assert.equal(compare(d("0.00"), d("-0")), 0); for (const z of ["0", "0.0", "0.00", "-0", "-0.000"]) { assert.equal(toString(d(z)), "0", z); } assert.equal(compare(d("-1.5"), d("-1.49")), -1); assert.equal(compare(d("10"), d("9.999")), 1); assert.equal(toString(d("-0.050")), "-0.05"); assert.equal(toString(d("100")), "100"); });