import { describe, expect, it } from "vitest" import { dt } from "@scandic-hotels/common/dt" import { getRelativePastTime } from "./getRelativePastTime" import type { IntlShape, MessageDescriptor } from "react-intl" const mockIntl = { formatMessage: ( descriptor: MessageDescriptor, values?: Record ) => { const messages: Record = { "common.nrDaysAgo": `{count, plural, one {# day ago} other {# days ago}}`, "common.nrMonthsAgo": `{count, plural, one {# month ago} other {# months ago}}`, "common.nrYearsAgo": `{count, plural, one {# year ago} other {# years ago}}`, } let message: string = messages[descriptor.id as string] || (typeof descriptor.defaultMessage === "string" ? descriptor.defaultMessage : "") || "" if (values) { // Handle plural forms first if (message.includes("{count, plural")) { const count = values.count as number if (count === 1) { // Extract the singular form (between "one {" and "}") const singularMatch = message.match(/one {(.*?)}/) if (singularMatch) { message = singularMatch[1].replace("#", String(count)) } } else { // Extract the plural form (between "other {" and "}") const pluralMatch = message.match(/other {(.*?)}/) if (pluralMatch) { message = pluralMatch[1].replace("#", String(count)) } } } // Replace any remaining placeholders Object.entries(values).forEach(([key, value]) => { message = message.replace(`{${key}}`, String(value)) }) } return message }, } as IntlShape describe("getRelativePastTime", () => { describe("days ago (1-30 days)", () => { it("should return '1 day ago' for yesterday", () => { const yesterday = dt().subtract(1, "day").format("YYYY-MM-DD") const result = getRelativePastTime(yesterday, mockIntl) expect(result).toBe("1 day ago") }) it("should return '2 days ago' for 2 days ago", () => { const twoDaysAgo = dt().subtract(2, "days").format("YYYY-MM-DD") const result = getRelativePastTime(twoDaysAgo, mockIntl) expect(result).toBe("2 days ago") }) it("should return '15 days ago' for 15 days ago", () => { const fifteenDaysAgo = dt().subtract(15, "days").format("YYYY-MM-DD") const result = getRelativePastTime(fifteenDaysAgo, mockIntl) expect(result).toBe("15 days ago") }) it("should return '30 days ago' for exactly 30 days ago (boundary)", () => { const thirtyDaysAgo = dt().subtract(30, "days").format("YYYY-MM-DD") const result = getRelativePastTime(thirtyDaysAgo, mockIntl) expect(result).toBe("30 days ago") }) it("should handle the full range from 1 to 30 days ago", () => { for (let days = 1; days <= 30; days++) { const pastDate = dt().subtract(days, "days").format("YYYY-MM-DD") const result = getRelativePastTime(pastDate, mockIntl) if (days === 1) { expect(result).toBe("1 day ago") } else { expect(result).toBe(`${days} days ago`) } } }) }) describe("months ago (31-364 days)", () => { it("should return '1 month ago' for 31 days ago", () => { const thirtyOneDaysAgo = dt().subtract(31, "days").format("YYYY-MM-DD") const result = getRelativePastTime(thirtyOneDaysAgo, mockIntl) expect(result).toBe("1 month ago") }) it("should return '1 month ago' for 45 days ago", () => { const fortyFiveDaysAgo = dt().subtract(45, "days").format("YYYY-MM-DD") const result = getRelativePastTime(fortyFiveDaysAgo, mockIntl) expect(result).toBe("1 month ago") }) it("should return '2 months ago' for 60 days ago", () => { const sixtyDaysAgo = dt().subtract(60, "days").format("YYYY-MM-DD") const result = getRelativePastTime(sixtyDaysAgo, mockIntl) expect(result).toBe("2 months ago") }) it("should return '6 months ago' for 180 days ago", () => { const sixMonthsAgo = dt().subtract(180, "days").format("YYYY-MM-DD") const result = getRelativePastTime(sixMonthsAgo, mockIntl) expect(result).toBe("6 months ago") }) it("should return '11 months ago' for 330 days ago", () => { const elevenMonthsAgo = dt().subtract(330, "days").format("YYYY-MM-DD") const result = getRelativePastTime(elevenMonthsAgo, mockIntl) expect(result).toBe("11 months ago") }) it("should return '12 months ago' for 364 days ago (boundary)", () => { const twelveMonthsAgo = dt().subtract(364, "days").format("YYYY-MM-DD") const result = getRelativePastTime(twelveMonthsAgo, mockIntl) expect(result).toBe("12 months ago") }) }) describe("years ago (365+ days)", () => { it("should return '1 year ago' for exactly 365 days ago", () => { const oneYearAgo = dt().subtract(365, "days").format("YYYY-MM-DD") const result = getRelativePastTime(oneYearAgo, mockIntl) expect(result).toBe("1 year ago") }) it("should return '1 year ago' for 400 days ago", () => { const fourHundredDaysAgo = dt().subtract(400, "days").format("YYYY-MM-DD") const result = getRelativePastTime(fourHundredDaysAgo, mockIntl) expect(result).toBe("1 year ago") }) it("should return '2 years ago' for 730 days ago", () => { const twoYearsAgo = dt().subtract(730, "days").format("YYYY-MM-DD") const result = getRelativePastTime(twoYearsAgo, mockIntl) expect(result).toBe("2 years ago") }) it("should return '5 years ago' for 5 years ago", () => { const fiveYearsAgo = dt().subtract(5, "years").format("YYYY-MM-DD") const result = getRelativePastTime(fiveYearsAgo, mockIntl) expect(result).toBe("5 years ago") }) }) describe("edge cases", () => { it("should handle dates with different time components consistently", () => { // The function calculates exact day differences, so time components matter // Using start of day to ensure consistent results const dateWithTime1 = dt() .subtract(5, "days") .startOf("day") .format("YYYY-MM-DD HH:mm") const dateWithTime2 = dt() .subtract(5, "days") .startOf("day") .format("YYYY-MM-DD HH:mm") const result1 = getRelativePastTime(dateWithTime1, mockIntl) const result2 = getRelativePastTime(dateWithTime2, mockIntl) expect(result1).toBe("5 days ago") expect(result2).toBe("5 days ago") }) it("should handle ISO date strings with timezone", () => { const isoDate = dt().subtract(7, "days").toISOString() const result = getRelativePastTime(isoDate, mockIntl) expect(result).toBe("7 days ago") }) it("should handle future dates (should return 0 days ago for same day)", () => { // The function doesn't handle negative days specially - it just uses the diff calculation // For future dates on the same day, diff will be 0 const futureDate = dt().add(1, "day").startOf("day").format("YYYY-MM-DD") const result = getRelativePastTime(futureDate, mockIntl) expect(result).toBe("0 days ago") }) }) describe("boundary transitions", () => { it("should transition correctly from days to months at 31 days", () => { const date30 = dt().subtract(30, "days").format("YYYY-MM-DD") const date31 = dt().subtract(31, "days").format("YYYY-MM-DD") expect(getRelativePastTime(date30, mockIntl)).toBe("30 days ago") expect(getRelativePastTime(date31, mockIntl)).toBe("1 month ago") }) it("should transition correctly from months to years at 365 days", () => { const date364 = dt().subtract(364, "days").format("YYYY-MM-DD") const date365 = dt().subtract(365, "days").format("YYYY-MM-DD") expect(getRelativePastTime(date364, mockIntl)).toBe("12 months ago") expect(getRelativePastTime(date365, mockIntl)).toBe("1 year ago") }) it("should handle the transition from 1 day to multiple days", () => { const date1 = dt().subtract(1, "day").format("YYYY-MM-DD") const date2 = dt().subtract(2, "days").format("YYYY-MM-DD") expect(getRelativePastTime(date1, mockIntl)).toBe("1 day ago") expect(getRelativePastTime(date2, mockIntl)).toBe("2 days ago") }) }) })