xtap-pool / explorer /tests /format.test.ts
osolmaz's picture
osolmaz HF Staff
deploy: d7bc9a8
492326f verified
Raw
History Blame Contribute Delete
4.92 kB
import { describe, expect, it } from "vitest";
import {
avatarColor,
displayName,
formatCount,
formatTweetDate,
isArticleTweet,
isRetweet,
nextTweetDateRefreshDelay,
photoMedia,
quotedTweetUrl,
tokenizeTweetText,
tweetMetrics,
tweetTextHtml,
} from "../src/lib/format.js";
import { pooledTweet } from "./fixtures.js";
const NOW = new Date("2026-07-06T12:00:00.000Z");
describe("tokenizeTweetText", () => {
it("linkifies urls, mentions and hashtags between plain text", () => {
const segments = tokenizeTweetText("Hey @alice check https://example.com/x #ai now");
expect(segments).toEqual([
{ kind: "text", text: "Hey " },
{ kind: "link", text: "@alice", href: "https://x.com/alice" },
{ kind: "text", text: " check " },
{ kind: "link", text: "https://example.com/x", href: "https://example.com/x" },
{ kind: "text", text: " " },
{ kind: "link", text: "#ai", href: "https://x.com/hashtag/ai" },
{ kind: "text", text: " now" },
]);
});
it("returns one plain segment for text without tokens", () => {
expect(tokenizeTweetText("just words")).toEqual([{ kind: "text", text: "just words" }]);
expect(tokenizeTweetText("")).toEqual([]);
});
});
describe("tweetTextHtml", () => {
it("escapes markup and linkifies tokens", () => {
expect(tweetTextHtml('a <b> & "quote" @alice')).toBe(
'a &lt;b&gt; &amp; &quot;quote&quot; <a href="https://x.com/alice" target="_blank" ' +
'rel="noopener noreferrer">@alice</a>',
);
});
it("escapes link text and hrefs", () => {
expect(tweetTextHtml("https://e.com/?a=1&b=2")).toBe(
'<a href="https://e.com/?a=1&amp;b=2" target="_blank" rel="noopener noreferrer">' +
"https://e.com/?a=1&amp;b=2</a>",
);
});
});
describe("formatCount", () => {
it("formats X-style compact counts", () => {
expect(formatCount(0)).toBe("0");
expect(formatCount(999)).toBe("999");
expect(formatCount(1000)).toBe("1K");
expect(formatCount(1234)).toBe("1.2K");
expect(formatCount(87845)).toBe("87.8K");
expect(formatCount(2_500_000)).toBe("2.5M");
});
});
describe("formatTweetDate", () => {
it("uses relative labels within a day and dates beyond", () => {
expect(formatTweetDate("2026-07-06T11:59:30.000Z", NOW)).toBe("now");
expect(formatTweetDate("2026-07-06T11:15:00.000Z", NOW)).toBe("45m");
expect(formatTweetDate("2026-07-06T02:00:00.000Z", NOW)).toBe("10h");
expect(formatTweetDate("2026-05-21T03:04:35.954Z", NOW)).toBe("May 21");
expect(formatTweetDate("2024-12-31T00:00:00.000Z", NOW)).toBe("Dec 31, 2024");
});
it("returns when relative labels need to refresh", () => {
expect(nextTweetDateRefreshDelay("2026-07-06T11:59:30.000Z", NOW)).toBe(30_100);
expect(nextTweetDateRefreshDelay("2026-07-06T11:15:45.000Z", NOW)).toBe(45_100);
expect(nextTweetDateRefreshDelay("2026-07-06T02:30:00.000Z", NOW)).toBe(1_800_100);
expect(nextTweetDateRefreshDelay("2026-05-21T03:04:35.954Z", NOW)).toBeUndefined();
});
});
describe("tweet field helpers", () => {
it("extracts up to four photos with alt text", () => {
const tweet = pooledTweet({
media: [
{ type: "photo", url: "https://pbs/1.jpg", alt_text: "one" },
{ type: "video", url: "https://pbs/skip.mp4" },
{ type: "photo", url: "https://pbs/2.jpg" },
{ type: "photo", url: "https://pbs/3.jpg" },
{ type: "photo", url: "https://pbs/4.jpg" },
{ type: "photo", url: "https://pbs/5.jpg" },
],
});
const photos = photoMedia(tweet);
expect(photos).toHaveLength(4);
expect(photos[0]).toEqual({ url: "https://pbs/1.jpg", alt: "one" });
expect(photos[1]).toEqual({ url: "https://pbs/2.jpg", alt: "Tweet image" });
expect(photoMedia(pooledTweet({ media: "nope" }))).toEqual([]);
});
it("reads metrics with zero defaults", () => {
expect(tweetMetrics(pooledTweet({ metrics: { likes: 7, views: null } }))).toEqual({
replies: 0,
retweets: 0,
likes: 7,
views: 0,
});
expect(tweetMetrics(pooledTweet({ metrics: undefined })).likes).toBe(0);
});
it("derives display name, flags and quote URL", () => {
expect(displayName(pooledTweet())).toBe("Some One");
expect(displayName(pooledTweet({ author: { username: "bare" } }))).toBe("bare");
expect(isArticleTweet(pooledTweet({ is_article: true }))).toBe(true);
expect(isArticleTweet(pooledTweet())).toBe(false);
expect(isRetweet(pooledTweet({ is_retweet: true }))).toBe(true);
expect(quotedTweetUrl(pooledTweet({ quoted_tweet_id: "42" }))).toBe(
"https://x.com/i/status/42",
);
expect(quotedTweetUrl(pooledTweet())).toBeUndefined();
});
it("produces stable avatar colors", () => {
expect(avatarColor("osolmaz")).toBe(avatarColor("osolmaz"));
expect(avatarColor("osolmaz")).toMatch(/^hsl\(\d+ 55% 45%\)$/);
});
});