Spaces:
Running
Running
| import { describe, expect, it } from "vitest"; | |
| import { | |
| formatRelativeTime, | |
| getHostname, | |
| getSemanticVersion, | |
| groupSearchResultsByDate, | |
| searchWithFuzzy, | |
| } from "./stringFormatters"; | |
| describe("stringFormatters", () => { | |
| describe("getHostname", () => { | |
| it("should extract hostname from valid URL", () => { | |
| expect(getHostname("https://example.com/page")).toBe("example.com"); | |
| }); | |
| it("should remove www prefix", () => { | |
| expect(getHostname("https://www.example.com/page")).toBe("example.com"); | |
| }); | |
| it("should handle http URLs", () => { | |
| expect(getHostname("http://test.org/path")).toBe("test.org"); | |
| }); | |
| it("should return original string for invalid URL", () => { | |
| expect(getHostname("not-a-url")).toBe("not-a-url"); | |
| }); | |
| it("should handle URL with port (hostname only)", () => { | |
| expect(getHostname("https://localhost:3000")).toBe("localhost"); | |
| }); | |
| }); | |
| describe("getSemanticVersion", () => { | |
| it("should convert number timestamp to YYYY.MM.DD format", () => { | |
| const result = getSemanticVersion(1700000000000); | |
| expect(result).toMatch(/^\d{4}\.\d{1,2}\.\d{1,2}$/); | |
| }); | |
| it("should handle Date object", () => { | |
| const result = getSemanticVersion(new Date(2024, 0, 15)); | |
| expect(result).toBe("2024.1.15"); | |
| }); | |
| it("should handle ISO date string", () => { | |
| const result = getSemanticVersion("2024-06-01"); | |
| expect(result).toMatch(/^2024\.6\.1$/); | |
| }); | |
| }); | |
| describe("formatRelativeTime", () => { | |
| it("should return Just now for recent timestamp", () => { | |
| const now = Date.now(); | |
| expect(formatRelativeTime(now)).toBe("Just now"); | |
| }); | |
| it("should return minutes ago", () => { | |
| const fiveMinutesAgo = Date.now() - 5 * 60 * 1000; | |
| expect(formatRelativeTime(fiveMinutesAgo)).toBe("5m ago"); | |
| }); | |
| it("should return hours ago", () => { | |
| const twoHoursAgo = Date.now() - 2 * 60 * 60 * 1000; | |
| expect(formatRelativeTime(twoHoursAgo)).toBe("2h ago"); | |
| }); | |
| it("should return days ago", () => { | |
| const threeDaysAgo = Date.now() - 3 * 24 * 60 * 60 * 1000; | |
| expect(formatRelativeTime(threeDaysAgo)).toBe("3d ago"); | |
| }); | |
| it("should return locale date for older timestamps", () => { | |
| const oldTimestamp = Date.now() - 30 * 24 * 60 * 60 * 1000; | |
| const result = formatRelativeTime(oldTimestamp); | |
| expect(result).not.toContain("ago"); | |
| }); | |
| }); | |
| describe("searchWithFuzzy", () => { | |
| const items = [ | |
| { id: 1, name: "apple" }, | |
| { id: 2, name: "application" }, | |
| { id: 3, name: "banana" }, | |
| { id: 4, name: "blueprint" }, | |
| ]; | |
| it("should return all items with score 0 for empty query", () => { | |
| const results = searchWithFuzzy(items, "", (item) => item.name); | |
| expect(results).toHaveLength(4); | |
| expect(results.every((r) => r.score === 0)).toBe(true); | |
| }); | |
| it("should find matches with fuzzy search", () => { | |
| const results = searchWithFuzzy(items, "app", (item) => item.name); | |
| expect(results.length).toBeGreaterThan(0); | |
| expect(results[0].item.name).toContain("app"); | |
| }); | |
| it("should respect limit parameter", () => { | |
| const results = searchWithFuzzy(items, "a", (item) => item.name, 2); | |
| expect(results).toHaveLength(2); | |
| }); | |
| it("should return empty array for no matches", () => { | |
| const results = searchWithFuzzy(items, "xyz", (item) => item.name); | |
| expect(results).toHaveLength(0); | |
| }); | |
| it("should return scores between 0 and 1", () => { | |
| const results = searchWithFuzzy(items, "a", (item) => item.name); | |
| results.forEach((r) => { | |
| expect(r.score).toBeGreaterThanOrEqual(0); | |
| expect(r.score).toBeLessThanOrEqual(1); | |
| }); | |
| }); | |
| }); | |
| describe("groupSearchResultsByDate", () => { | |
| it("should group items by Today", () => { | |
| const now = Date.now(); | |
| const items = [{ item: { id: 1 }, timestamp: now }]; | |
| const groups = groupSearchResultsByDate(items); | |
| expect(groups.Today).toHaveLength(1); | |
| }); | |
| it("should group items by Yesterday", () => { | |
| const yesterday = Date.now() - 24 * 60 * 60 * 1000; | |
| const items = [{ item: { id: 1 }, timestamp: yesterday }]; | |
| const groups = groupSearchResultsByDate(items); | |
| expect(groups.Yesterday).toHaveLength(1); | |
| }); | |
| it("should group items by This Week", () => { | |
| const threeDaysAgo = Date.now() - 3 * 24 * 60 * 60 * 1000; | |
| const items = [{ item: { id: 1 }, timestamp: threeDaysAgo }]; | |
| const groups = groupSearchResultsByDate(items); | |
| expect(groups["This Week"]).toHaveLength(1); | |
| }); | |
| it("should group older items by month", () => { | |
| const oldTimestamp = Date.now() - 30 * 24 * 60 * 60 * 1000; | |
| const items = [{ item: { id: 1 }, timestamp: oldTimestamp }]; | |
| const groups = groupSearchResultsByDate(items); | |
| const keys = Object.keys(groups); | |
| expect(keys.length).toBe(1); | |
| expect(keys[0]).toMatch(/^\w{3} \d{4}$/); | |
| }); | |
| it("should handle empty array", () => { | |
| const groups = groupSearchResultsByDate([]); | |
| expect(Object.keys(groups)).toHaveLength(0); | |
| }); | |
| it("should group multiple items in same category", () => { | |
| const now = Date.now(); | |
| const items = [ | |
| { item: { id: 1 }, timestamp: now }, | |
| { item: { id: 2 }, timestamp: now - 60 * 1000 }, | |
| ]; | |
| const groups = groupSearchResultsByDate(items); | |
| expect(groups.Today).toHaveLength(2); | |
| }); | |
| }); | |
| }); | |