mirror of
https://git.quad4.io/RNS-Things/MeshChatX.git
synced 2026-05-03 10:55:13 +00:00
112 lines
4.3 KiB
JavaScript
112 lines
4.3 KiB
JavaScript
import { describe, it, expect } from "vitest";
|
|
import {
|
|
TIMESTAMP_CLUSTER_GAP_MS,
|
|
buildTimestampGroupedOldestFirst,
|
|
calendarDayKeyFromDate,
|
|
displayGroupIsOutbound,
|
|
displayGroupSortBoundsMs,
|
|
} from "../../meshchatx/src/frontend/js/messageTimestampGrouping.js";
|
|
|
|
describe("messageTimestampGrouping", () => {
|
|
it("calendarDayKeyFromDate uses local calendar fields", () => {
|
|
const d = new Date(2026, 3, 26, 23, 59);
|
|
expect(calendarDayKeyFromDate(d)).toBe("2026-04-26");
|
|
});
|
|
|
|
it("inserts a date divider when calendar day changes", () => {
|
|
const a = {
|
|
type: "single",
|
|
key: "a",
|
|
chatItem: { is_outbound: false, lxmf_message: { created_at: "2026-04-25T12:00:00Z", hash: "a" } },
|
|
};
|
|
const b = {
|
|
type: "single",
|
|
key: "b",
|
|
chatItem: { is_outbound: false, lxmf_message: { created_at: "2026-04-28T12:00:00Z", hash: "b" } },
|
|
};
|
|
const out = buildTimestampGroupedOldestFirst([a, b]);
|
|
const dividers = out.filter((x) => x.type === "dateDivider");
|
|
expect(dividers.length).toBeGreaterThanOrEqual(2);
|
|
expect(
|
|
out
|
|
.filter((x) => x.type === "single")
|
|
.map((x) => x.key)
|
|
.join(",")
|
|
).toBe("a,b");
|
|
});
|
|
|
|
it("hides timestamp on middle messages of a same-side cluster within gap", () => {
|
|
const t0 = "2026-04-26T12:00:00Z";
|
|
const t1 = "2026-04-26T12:01:00Z";
|
|
const t2 = "2026-04-26T12:02:00Z";
|
|
const m0 = {
|
|
type: "single",
|
|
key: "m0",
|
|
chatItem: { is_outbound: true, lxmf_message: { created_at: t0, hash: "h0" } },
|
|
};
|
|
const m1 = {
|
|
type: "single",
|
|
key: "m1",
|
|
chatItem: { is_outbound: true, lxmf_message: { created_at: t1, hash: "h1" } },
|
|
};
|
|
const m2 = {
|
|
type: "single",
|
|
key: "m2",
|
|
chatItem: { is_outbound: true, lxmf_message: { created_at: t2, hash: "h2" } },
|
|
};
|
|
const out = buildTimestampGroupedOldestFirst([m0, m1, m2]).filter((x) => x.type === "single");
|
|
expect(out[0].showTimestamp).toBe(false);
|
|
expect(out[1].showTimestamp).toBe(false);
|
|
expect(out[2].showTimestamp).toBe(true);
|
|
});
|
|
|
|
it("starts a new cluster after TIMESTAMP_CLUSTER_GAP_MS", () => {
|
|
const t0 = "2026-04-26T12:00:00Z";
|
|
const t1 = new Date(new Date(t0).getTime() + TIMESTAMP_CLUSTER_GAP_MS + 60 * 1000).toISOString();
|
|
const a = {
|
|
type: "single",
|
|
key: "a",
|
|
chatItem: { is_outbound: true, lxmf_message: { created_at: t0, hash: "a" } },
|
|
};
|
|
const b = {
|
|
type: "single",
|
|
key: "b",
|
|
chatItem: { is_outbound: true, lxmf_message: { created_at: t1, hash: "b" } },
|
|
};
|
|
const out = buildTimestampGroupedOldestFirst([a, b]).filter((x) => x.type === "single");
|
|
expect(out[0].showTimestamp).toBe(true);
|
|
expect(out[1].showTimestamp).toBe(true);
|
|
});
|
|
|
|
it("with grouping disabled, omits date dividers and shows timestamp on every message", () => {
|
|
const a = {
|
|
type: "single",
|
|
key: "a",
|
|
chatItem: { is_outbound: false, lxmf_message: { created_at: "2026-04-25T12:00:00Z", hash: "a" } },
|
|
};
|
|
const b = {
|
|
type: "single",
|
|
key: "b",
|
|
chatItem: { is_outbound: false, lxmf_message: { created_at: "2026-04-28T12:00:00Z", hash: "b" } },
|
|
};
|
|
const out = buildTimestampGroupedOldestFirst([a, b], { groupingEnabled: false });
|
|
expect(out.filter((x) => x.type === "dateDivider")).toHaveLength(0);
|
|
const singles = out.filter((x) => x.type === "single");
|
|
expect(singles.every((x) => x.showTimestamp === true)).toBe(true);
|
|
});
|
|
|
|
it("displayGroupSortBoundsMs spans image group min/max", () => {
|
|
const g = {
|
|
type: "imageGroup",
|
|
key: "ig",
|
|
items: [
|
|
{ is_outbound: true, lxmf_message: { created_at: "2026-04-26T12:00:00Z" } },
|
|
{ is_outbound: true, lxmf_message: { created_at: "2026-04-26T12:05:00Z" } },
|
|
],
|
|
};
|
|
const b = displayGroupSortBoundsMs(g);
|
|
expect(b.max - b.min).toBe(5 * 60 * 1000);
|
|
expect(displayGroupIsOutbound(g)).toBe(true);
|
|
});
|
|
});
|