From 5dbc4af8d92041ea31b0aeef430706e342016e9d Mon Sep 17 00:00:00 2001 From: longbiao Date: Wed, 27 May 2026 15:20:47 +0800 Subject: [PATCH] Add coverage tests for utility modules --- src/arrays.test.ts | 28 ++++++++++++++++++++++++++++ src/dates.test.ts | 39 +++++++++++++++++++++++++++++++++++++++ src/money.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ src/strings.test.ts | 33 ++++++++++++++++++++++++++++++++- 4 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 src/arrays.test.ts create mode 100644 src/dates.test.ts create mode 100644 src/money.test.ts diff --git a/src/arrays.test.ts b/src/arrays.test.ts new file mode 100644 index 0000000..68cf8e2 --- /dev/null +++ b/src/arrays.test.ts @@ -0,0 +1,28 @@ +import { describe, expect, it } from "vitest"; +import { chunk, dedupe, groupBy } from "./arrays"; + +describe("chunk", () => { + it("splits arrays into fixed-size groups and keeps the remainder", () => { + expect(chunk([1, 2, 3, 4, 5], 2)).toEqual([[1, 2], [3, 4], [5]]); + }); + + it("returns an empty list for non-positive sizes", () => { + expect(chunk([1, 2, 3], 0)).toEqual([]); + expect(chunk([1, 2, 3], -1)).toEqual([]); + }); +}); + +describe("dedupe", () => { + it("keeps first-seen values and removes later duplicates", () => { + expect(dedupe(["a", "b", "a", "c", "b"])).toEqual(["a", "b", "c"]); + }); +}); + +describe("groupBy", () => { + it("groups values by the key returned from the callback", () => { + expect(groupBy(["ant", "bat", "ape"], (value) => value[0])).toEqual({ + a: ["ant", "ape"], + b: ["bat"] + }); + }); +}); diff --git a/src/dates.test.ts b/src/dates.test.ts new file mode 100644 index 0000000..4de2997 --- /dev/null +++ b/src/dates.test.ts @@ -0,0 +1,39 @@ +import { describe, expect, it } from "vitest"; +import { addDays, daysBetween, isWeekend, startOfDayUTC } from "./dates"; + +describe("daysBetween", () => { + it("returns the rounded absolute day difference", () => { + const start = new Date("2026-05-01T12:00:00Z"); + const end = new Date("2026-05-04T00:00:00Z"); + + expect(daysBetween(start, end)).toBe(3); + expect(daysBetween(end, start)).toBe(3); + }); +}); + +describe("isWeekend", () => { + it("detects Saturday and Sunday", () => { + expect(isWeekend(new Date("2026-05-23T12:00:00Z"))).toBe(true); + expect(isWeekend(new Date("2026-05-24T12:00:00Z"))).toBe(true); + }); + + it("returns false for weekdays", () => { + expect(isWeekend(new Date("2026-05-25T12:00:00Z"))).toBe(false); + }); +}); + +describe("addDays", () => { + it("returns a new date shifted by the requested number of days", () => { + const original = new Date("2026-05-27T10:30:00Z"); + const shifted = addDays(original, 5); + + expect(shifted.toISOString()).toBe("2026-06-01T10:30:00.000Z"); + expect(original.toISOString()).toBe("2026-05-27T10:30:00.000Z"); + }); +}); + +describe("startOfDayUTC", () => { + it("normalizes a date to midnight UTC", () => { + expect(startOfDayUTC(new Date("2026-05-27T10:30:00Z")).toISOString()).toBe("2026-05-27T00:00:00.000Z"); + }); +}); diff --git a/src/money.test.ts b/src/money.test.ts new file mode 100644 index 0000000..20330af --- /dev/null +++ b/src/money.test.ts @@ -0,0 +1,40 @@ +import { describe, expect, it } from "vitest"; +import { formatCents, netPayoutCents, platformFeeCents, splitEvenly } from "./money"; + +describe("formatCents", () => { + it("formats USD and EUR with their symbols", () => { + expect(formatCents(1234)).toBe("$12.34"); + expect(formatCents(1234, "EUR")).toBe("€12.34"); + }); + + it("prefixes unknown currency codes", () => { + expect(formatCents(1234, "USDC")).toBe("USDC 12.34"); + }); +}); + +describe("platformFeeCents", () => { + it("rounds basis-point fees to the nearest cent", () => { + expect(platformFeeCents(12_345, 250)).toBe(309); + }); + + it("returns zero for non-positive gross amounts or fee rates", () => { + expect(platformFeeCents(0, 250)).toBe(0); + expect(platformFeeCents(12_345, 0)).toBe(0); + }); +}); + +describe("netPayoutCents", () => { + it("subtracts the platform fee from the gross amount", () => { + expect(netPayoutCents(10_000, 250)).toBe(9_750); + }); +}); + +describe("splitEvenly", () => { + it("distributes remainder cents to the earliest recipients", () => { + expect(splitEvenly(10, 3)).toEqual([4, 3, 3]); + }); + + it("returns an empty list for non-positive recipient counts", () => { + expect(splitEvenly(10, 0)).toEqual([]); + }); +}); diff --git a/src/strings.test.ts b/src/strings.test.ts index daeb1cc..e73910d 100644 --- a/src/strings.test.ts +++ b/src/strings.test.ts @@ -1,7 +1,38 @@ import { describe, it, expect } from "vitest"; -import { slugify } from "./strings"; +import { escapeHtml, slugify, titleCase, truncate } from "./strings"; + describe("slugify", () => { it("lowercases and dashifies basic input", () => { expect(slugify("Hello World")).toBe("hello-world"); }); + + it("removes punctuation, trims edge dashes, and collapses repeated dashes", () => { + expect(slugify(" Hello, Tiny--Utils!!! ")).toBe("hello-tiny-utils"); + }); +}); + +describe("truncate", () => { + it("returns the original string when it fits within the maximum", () => { + expect(truncate("short", 10)).toBe("short"); + }); + + it("shortens long strings and appends the suffix", () => { + expect(truncate("abcdef", 4)).toBe("abc…"); + }); + + it("returns an empty string for non-positive maximum lengths", () => { + expect(truncate("abcdef", 0)).toBe(""); + }); +}); + +describe("titleCase", () => { + it("capitalizes each word and lowercases the rest", () => { + expect(titleCase("hELLO tiny UTILS")).toBe("Hello Tiny Utils"); + }); +}); + +describe("escapeHtml", () => { + it("escapes HTML-sensitive characters", () => { + expect(escapeHtml(`Tom & 'Jerry'`)).toBe("<a href="x">Tom & 'Jerry'</a>"); + }); });