Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions src/arrays.test.ts
Original file line number Diff line number Diff line change
@@ -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" }],
});
});
});
29 changes: 29 additions & 0 deletions src/dates.test.ts
Original file line number Diff line number Diff line change
@@ -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",
);
});
});
27 changes: 27 additions & 0 deletions src/money.test.ts
Original file line number Diff line number Diff line change
@@ -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([]);
});
});
33 changes: 30 additions & 3 deletions src/strings.test.ts
Original file line number Diff line number Diff line change
@@ -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(`<a href="x">Tom & 'Jerry'</a>`)).toBe(
"&lt;a href=&quot;x&quot;&gt;Tom &amp; &#39;Jerry&#39;&lt;/a&gt;",
);
});
});