diff --git a/src/arrays.test.ts b/src/arrays.test.ts new file mode 100644 index 0000000..03aa9d2 --- /dev/null +++ b/src/arrays.test.ts @@ -0,0 +1,36 @@ +import { describe, expect, it } from "vitest"; +import { chunk, dedupe, groupBy } from "./arrays"; + +describe("array helpers", () => { + it("splits arrays into fixed-size chunks and keeps a short tail", () => { + expect(chunk([1, 2, 3, 4, 5], 2)).toEqual([[1, 2], [3, 4], [5]]); + }); + + it("returns an empty array for non-positive chunk sizes", () => { + expect(chunk([1, 2, 3], 0)).toEqual([]); + expect(chunk([1, 2, 3], -1)).toEqual([]); + }); + + it("deduplicates values while preserving first-seen order", () => { + expect(dedupe(["ts", "js", "ts", "go", "js"])).toEqual(["ts", "js", "go"]); + }); + + it("groups items by the key returned from the callback", () => { + const grouped = groupBy( + [ + { type: "fruit", name: "apple" }, + { type: "veg", name: "carrot" }, + { type: "fruit", name: "pear" }, + ], + (item) => item.type, + ); + + expect(grouped).toEqual({ + fruit: [ + { type: "fruit", name: "apple" }, + { type: "fruit", name: "pear" }, + ], + veg: [{ type: "veg", name: "carrot" }], + }); + }); +}); diff --git a/src/dates.test.ts b/src/dates.test.ts new file mode 100644 index 0000000..913b509 --- /dev/null +++ b/src/dates.test.ts @@ -0,0 +1,29 @@ +import { describe, expect, it } from "vitest"; +import { addDays, daysBetween, isWeekend, startOfDayUTC } from "./dates"; + +describe("date helpers", () => { + it("calculates absolute day differences", () => { + expect(daysBetween(new Date("2026-05-01T00:00:00Z"), new Date("2026-05-04T00:00:00Z"))).toBe(3); + expect(daysBetween(new Date("2026-05-04T00:00:00Z"), new Date("2026-05-01T00:00:00Z"))).toBe(3); + }); + + it("detects weekend days", () => { + expect(isWeekend(new Date("2026-05-30T12:00:00Z"))).toBe(true); + expect(isWeekend(new Date("2026-05-31T12:00:00Z"))).toBe(true); + expect(isWeekend(new Date("2026-05-29T12:00:00Z"))).toBe(false); + }); + + it("adds days without mutating the original date", () => { + const original = new Date("2026-05-29T10:30:00Z"); + const result = addDays(original, 5); + + expect(result.toISOString()).toBe("2026-06-03T10:30:00.000Z"); + expect(original.toISOString()).toBe("2026-05-29T10:30:00.000Z"); + }); + + it("returns the UTC start of the provided day", () => { + expect(startOfDayUTC(new Date("2026-05-29T23:59:59Z")).toISOString()).toBe( + "2026-05-29T00:00:00.000Z", + ); + }); +}); diff --git a/src/money.test.ts b/src/money.test.ts new file mode 100644 index 0000000..a81fa63 --- /dev/null +++ b/src/money.test.ts @@ -0,0 +1,27 @@ +import { describe, expect, it } from "vitest"; +import { formatCents, netPayoutCents, platformFeeCents, splitEvenly } from "./money"; + +describe("money helpers", () => { + it("formats cents for USD, EUR, and fallback currency codes", () => { + expect(formatCents(12345)).toBe("$123.45"); + expect(formatCents(987, "EUR")).toBe("€9.87"); + expect(formatCents(500, "GBP")).toBe("GBP 5.00"); + }); + + it("calculates platform fees in basis points and guards invalid inputs", () => { + expect(platformFeeCents(10_000, 250)).toBe(250); + expect(platformFeeCents(999, 333)).toBe(33); + expect(platformFeeCents(0, 250)).toBe(0); + expect(platformFeeCents(10_000, 0)).toBe(0); + }); + + it("subtracts platform fees from gross payout", () => { + expect(netPayoutCents(10_000, 250)).toBe(9_750); + }); + + it("splits cents evenly and distributes remainder to early recipients", () => { + expect(splitEvenly(10, 3)).toEqual([4, 3, 3]); + expect(splitEvenly(4, 2)).toEqual([2, 2]); + expect(splitEvenly(10, 0)).toEqual([]); + }); +}); diff --git a/src/strings.test.ts b/src/strings.test.ts index daeb1cc..add3e00 100644 --- a/src/strings.test.ts +++ b/src/strings.test.ts @@ -1,7 +1,34 @@ -import { describe, it, expect } from "vitest"; -import { slugify } from "./strings"; -describe("slugify", () => { +import { describe, expect, it } from "vitest"; +import { escapeHtml, slugify, titleCase, truncate } from "./strings"; + +describe("string helpers", () => { it("lowercases and dashifies basic input", () => { expect(slugify("Hello World")).toBe("hello-world"); }); + + it("removes punctuation and collapses repeated separators while slugifying", () => { + expect(slugify(" Hello, Tiny---Utils!! ")).toBe("hello-tiny-utils"); + }); + + it("truncates long strings with the default suffix", () => { + expect(truncate("abcdef", 4)).toBe("abc…"); + }); + + it("returns the original string when no truncation is needed", () => { + expect(truncate("abc", 4)).toBe("abc"); + }); + + it("returns an empty string for non-positive truncation lengths", () => { + expect(truncate("abc", 0)).toBe(""); + }); + + it("converts words to title case", () => { + expect(titleCase("hELLO tiny UTILS")).toBe("Hello Tiny Utils"); + }); + + it("escapes HTML-sensitive characters", () => { + expect(escapeHtml(`Tom & 'Jerry'`)).toBe( + "<a href="x">Tom & 'Jerry'</a>", + ); + }); });