test/shared/bulk-replace.test.ts
Rama main · réplica de lectura del repositorio original.
import { expect } from "@std/expect";
import { describe, it as test } from "@std/testing/bdd";
import {
applyNameReplacement,
buildDuplicatePreview,
computeDayOffset,
formatIsoForPreview,
shiftUtcIsoByDays,
} from "#shared/bulk-replace.ts";
describe("bulk-replace", () => {
describe("applyNameReplacement", () => {
test("replaces every occurrence of the find substring", () => {
expect(
applyNameReplacement("Spring Workshop Spring", "Spring", "Autumn"),
).toBe("Autumn Workshop Autumn");
});
test("returns the original name when find is empty", () => {
expect(applyNameReplacement("Spring 2026", "", "anything")).toBe(
"Spring 2026",
);
});
test("leaves the name unchanged when find is absent", () => {
expect(applyNameReplacement("Summer 2026", "Spring", "Autumn")).toBe(
"Summer 2026",
);
});
test("allows deleting the find substring by using empty replace", () => {
expect(applyNameReplacement("Spring Workshop", "Spring ", "")).toBe(
"Workshop",
);
});
});
describe("computeDayOffset", () => {
test("returns the day count between two dates (replace - find)", () => {
expect(computeDayOffset("2026-04-16", "2026-04-23")).toBe(7);
});
test("returns a negative offset when replace is earlier", () => {
expect(computeDayOffset("2026-04-23", "2026-04-16")).toBe(-7);
});
test("spans months and years correctly", () => {
expect(computeDayOffset("2026-12-31", "2027-01-02")).toBe(2);
});
test("returns 0 when either date is empty", () => {
expect(computeDayOffset("", "2026-04-23")).toBe(0);
expect(computeDayOffset("2026-04-16", "")).toBe(0);
});
});
describe("shiftUtcIsoByDays", () => {
test("adds days to a UTC ISO datetime", () => {
expect(shiftUtcIsoByDays("2026-04-16T09:00:00.000Z", 7)).toBe(
"2026-04-23T09:00:00.000Z",
);
});
test("accepts negative offsets", () => {
expect(shiftUtcIsoByDays("2026-04-16T09:00:00.000Z", -1)).toBe(
"2026-04-15T09:00:00.000Z",
);
});
test("returns the input unchanged for zero-day offsets", () => {
const iso = "2026-04-16T09:00:00.000Z";
expect(shiftUtcIsoByDays(iso, 0)).toBe(iso);
});
test("returns the exact input string for zero-day offsets, not a reparsed equivalent", () => {
// A non-canonical-but-equivalent ISO string (no milliseconds) is
// Date-parseable, but `new Date(...).toISOString()` would normalize it
// to a *different* string (".000" appended) — so this only passes if
// the zero-day short-circuit actually returns the input untouched
// rather than recomputing through Date.parse/toISOString.
const iso = "2026-04-16T09:00:00Z";
expect(shiftUtcIsoByDays(iso, 0)).toBe(iso);
});
test("returns empty string for empty input", () => {
expect(shiftUtcIsoByDays("", 5)).toBe("");
});
});
describe("buildDuplicatePreview", () => {
const listings = [
{ date: "2026-04-16T09:00:00.000Z", id: 1, name: "Spring Workshop" },
{ date: "2026-04-18T12:00:00.000Z", id: 2, name: "Spring Picnic" },
];
test("applies both name and date replacements across all listings", () => {
const rows = buildDuplicatePreview(listings, {
dateFind: "2026-04-16",
dateReplace: "2026-04-23",
nameFind: "Spring",
nameReplace: "Autumn",
});
expect(rows).toEqual([
{
id: 1,
newDate: "2026-04-23T09:00:00.000Z",
newName: "Autumn Workshop",
originalDate: "2026-04-16T09:00:00.000Z",
originalName: "Spring Workshop",
},
{
id: 2,
newDate: "2026-04-25T12:00:00.000Z",
newName: "Autumn Picnic",
originalDate: "2026-04-18T12:00:00.000Z",
originalName: "Spring Picnic",
},
]);
});
test("echoes the original values when no replacements are set", () => {
const rows = buildDuplicatePreview(listings, {
dateFind: "",
dateReplace: "",
nameFind: "",
nameReplace: "",
});
expect(rows[0]!.newName).toBe("Spring Workshop");
expect(rows[0]!.newDate).toBe("2026-04-16T09:00:00.000Z");
});
test("returns an empty array when the group has no listings", () => {
expect(
buildDuplicatePreview([], {
dateFind: "2026-04-16",
dateReplace: "2026-04-23",
nameFind: "Spring",
nameReplace: "Autumn",
}),
).toEqual([]);
});
});
describe("formatIsoForPreview", () => {
test("formats a UTC ISO string in the configured timezone", () => {
expect(
formatIsoForPreview("2026-06-15T13:00:00.000Z", "Europe/London"),
).toBe("2026-06-15 14:00");
});
test("returns empty string for empty input", () => {
expect(formatIsoForPreview("", "Europe/London")).toBe("");
});
});
});