mirror of
https://github.com/Zproger/Aurum.git
synced 2026-10-13 11:06:40 +07:00
test: юнит-тесты на форматирование и разбивки крипто-портфеля + версия 1.1.6
Vitest для чистой логики: lib/format.ts (заодно поймал баг в trimTrailingZeros на "-0.000") и расчёт разбивки по риску/монете/сети на вкладке Crypto — вынес их из компонентов в отдельные тестируемые функции. Тесты подключены в CI. Версия приложения обновлена до 1.1.6.
This commit is contained in:
155
frontend/src/lib/format.test.ts
Normal file
155
frontend/src/lib/format.test.ts
Normal file
@@ -0,0 +1,155 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { setLanguage } from "@/lib/i18n";
|
||||
import {
|
||||
formatCryptoAmount,
|
||||
formatCurrency,
|
||||
formatSignedCurrency,
|
||||
formatTransactionDate,
|
||||
getIntlLocale,
|
||||
getMonthLabels,
|
||||
maskAmount,
|
||||
pluralizeRu,
|
||||
trimTrailingZeros,
|
||||
} from "@/lib/format";
|
||||
|
||||
describe("getIntlLocale", () => {
|
||||
it("maps ru to ru-RU and en to en-US", () => {
|
||||
expect(getIntlLocale("ru")).toBe("ru-RU");
|
||||
expect(getIntlLocale("en")).toBe("en-US");
|
||||
});
|
||||
});
|
||||
|
||||
describe("formatCurrency", () => {
|
||||
beforeEach(() => setLanguage("en"));
|
||||
|
||||
it("keeps unambiguous currency symbols compact, not spelled out", () => {
|
||||
// The exact regression this suite exists to catch: currencyDisplay
|
||||
// "code" would turn this into "USD 614" — see lib/format.ts's
|
||||
// createCurrencyFormatter docstring and the PR #18 review that flagged it.
|
||||
expect(formatCurrency(614, "USD")).toBe("$614");
|
||||
});
|
||||
|
||||
it("drops the region prefix on ambiguous symbols (CNY, HKD) instead of spelling out the code", () => {
|
||||
const cny = formatCurrency(614, "CNY");
|
||||
const hkd = formatCurrency(614, "HKD");
|
||||
expect(cny).not.toContain("CN¥");
|
||||
expect(cny).not.toContain("CNY");
|
||||
expect(hkd).not.toContain("HK$");
|
||||
expect(hkd).not.toContain("HKD");
|
||||
});
|
||||
|
||||
it("rounds to whole units", () => {
|
||||
expect(formatCurrency(614.5, "USD")).toBe("$615");
|
||||
expect(formatCurrency(614.4, "USD")).toBe("$614");
|
||||
});
|
||||
|
||||
it("accepts a numeric string the same as a number", () => {
|
||||
expect(formatCurrency("614", "USD")).toBe(formatCurrency(614, "USD"));
|
||||
});
|
||||
});
|
||||
|
||||
describe("formatCryptoAmount", () => {
|
||||
beforeEach(() => setLanguage("en"));
|
||||
|
||||
it("uses 2 decimals once the value reaches 1", () => {
|
||||
expect(formatCryptoAmount(1234.5678, "USD")).toBe("$1,234.57");
|
||||
});
|
||||
|
||||
it("uses 2 decimals for exactly zero", () => {
|
||||
expect(formatCryptoAmount(0, "USD")).toBe("$0.00");
|
||||
});
|
||||
|
||||
it("scales precision for sub-cent values so they don't round away to $0.00", () => {
|
||||
// 8 leading zeros after the decimal point + 4 digits of real precision.
|
||||
expect(formatCryptoAmount(0.000000006894, "USD")).toBe("$0.000000006894");
|
||||
});
|
||||
});
|
||||
|
||||
describe("formatSignedCurrency", () => {
|
||||
beforeEach(() => setLanguage("en"));
|
||||
|
||||
it("prefixes a plus sign on positive amounts", () => {
|
||||
expect(formatSignedCurrency(100, "USD")).toBe("+$100");
|
||||
});
|
||||
|
||||
it("leaves the formatter's own minus sign on negative amounts, no double sign", () => {
|
||||
expect(formatSignedCurrency(-100, "USD")).toBe("-$100");
|
||||
});
|
||||
|
||||
it("adds no sign for zero", () => {
|
||||
expect(formatSignedCurrency(0, "USD")).toBe("$0");
|
||||
});
|
||||
});
|
||||
|
||||
describe("maskAmount", () => {
|
||||
it("replaces the formatted value when hidden", () => {
|
||||
expect(maskAmount("$1,234", true)).toBe("••••");
|
||||
});
|
||||
|
||||
it("passes the formatted value through when not hidden", () => {
|
||||
expect(maskAmount("$1,234", false)).toBe("$1,234");
|
||||
});
|
||||
});
|
||||
|
||||
describe("trimTrailingZeros", () => {
|
||||
it("strips a wei-level all-zero fractional part down to the integer", () => {
|
||||
expect(trimTrailingZeros("3.000000000000000000")).toBe("3");
|
||||
});
|
||||
|
||||
it("trims only the trailing zeros, keeping real precision", () => {
|
||||
expect(trimTrailingZeros("3.140000")).toBe("3.14");
|
||||
});
|
||||
|
||||
it("leaves a value with no decimal point untouched", () => {
|
||||
expect(trimTrailingZeros("42")).toBe("42");
|
||||
});
|
||||
|
||||
it("collapses an all-zero fractional part to a bare 0, not empty or a dangling minus", () => {
|
||||
expect(trimTrailingZeros("0.000")).toBe("0");
|
||||
expect(trimTrailingZeros("-0.000")).toBe("0");
|
||||
});
|
||||
});
|
||||
|
||||
describe("getMonthLabels", () => {
|
||||
it("returns 12 labels for each language", () => {
|
||||
expect(getMonthLabels("en")).toHaveLength(12);
|
||||
expect(getMonthLabels("ru")).toHaveLength(12);
|
||||
});
|
||||
|
||||
it("starts January in both languages", () => {
|
||||
expect(getMonthLabels("en")[0]).toBe("Jan");
|
||||
expect(getMonthLabels("ru")[0]).toBe("Янв");
|
||||
});
|
||||
});
|
||||
|
||||
describe("formatTransactionDate", () => {
|
||||
it("omits the year by default", () => {
|
||||
expect(formatTransactionDate("2026-08-29", false)).toBe(getIntlLocale("en") === "en-US" ? "Aug 29" : "Aug 29");
|
||||
});
|
||||
|
||||
it("includes the year when asked", () => {
|
||||
expect(formatTransactionDate("2026-08-29", true)).toContain("2026");
|
||||
});
|
||||
});
|
||||
|
||||
describe("pluralizeRu", () => {
|
||||
it("picks the singular form for 1 (and 21, 31, ... but not 11)", () => {
|
||||
expect(pluralizeRu(1, "актив", "актива", "активов")).toBe("актив");
|
||||
expect(pluralizeRu(21, "актив", "актива", "активов")).toBe("актив");
|
||||
expect(pluralizeRu(11, "актив", "актива", "активов")).not.toBe("актив");
|
||||
});
|
||||
|
||||
it("picks the few form for 2-4 (and 22-24, but not 12-14)", () => {
|
||||
expect(pluralizeRu(2, "актив", "актива", "активов")).toBe("актива");
|
||||
expect(pluralizeRu(4, "актив", "актива", "активов")).toBe("актива");
|
||||
expect(pluralizeRu(22, "актив", "актива", "активов")).toBe("актива");
|
||||
expect(pluralizeRu(12, "актив", "актива", "активов")).toBe("активов");
|
||||
});
|
||||
|
||||
it("picks the many form for 0, 5-20, and 11-14", () => {
|
||||
expect(pluralizeRu(0, "актив", "актива", "активов")).toBe("активов");
|
||||
expect(pluralizeRu(5, "актив", "актива", "активов")).toBe("активов");
|
||||
expect(pluralizeRu(11, "актив", "актива", "активов")).toBe("активов");
|
||||
expect(pluralizeRu(14, "актив", "актива", "активов")).toBe("активов");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user