






















11// Telegram tests cover topic name cache plugin behavior.
22import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
33import {
4-clearTopicNameCache,
5-getTopicEntry,
64getTopicName,
75resetTopicNameCacheForTest,
86setTelegramTopicNameStoreFactoryForTest,
9-topicNameCacheSize,
107updateTopicName,
118} from "./topic-name-cache.js";
12913-type TopicEntry = NonNullable<Awaited<ReturnType<typeof getTopicEntry>>>;
10+type TopicEntry = {
11+name: string;
12+iconColor?: number;
13+iconCustomEmojiId?: string;
14+closed?: boolean;
15+updatedAt: number;
16+};
17+18+function topicKey(chatId: number | string, threadId: number | string): string {
19+return `${chatId}:${threadId}`;
20+}
21+22+function getStoredTopicEntry(
23+stores: Map<string, Map<string, TopicEntry>>,
24+chatId: number | string,
25+threadId: number | string,
26+): TopicEntry | undefined {
27+const key = topicKey(chatId, threadId);
28+for (const entries of stores.values()) {
29+const entry = entries.get(key);
30+if (entry) {
31+return entry;
32+}
33+}
34+return undefined;
35+}
36+37+function topicStoreSize(stores: Map<string, Map<string, TopicEntry>>): number {
38+return Array.from(stores.values(), (entries) => entries.size).reduce(
39+(total, size) => total + size,
40+0,
41+);
42+}
14431544function installMemoryStores() {
1645const stores = new Map<string, Map<string, TopicEntry>>();
@@ -36,10 +65,11 @@ function installMemoryStores() {
3665}
37663867describe("topic-name-cache", () => {
68+let stores: Map<string, Map<string, TopicEntry>>;
69+3970beforeEach(async () => {
4071vi.useRealTimers();
41-installMemoryStores();
42-await clearTopicNameCache();
72+stores = installMemoryStores();
4373resetTopicNameCacheForTest();
4474});
4575@@ -67,13 +97,13 @@ describe("topic-name-cache", () => {
6797await updateTopicName(-100123, 42, { name: "Deployments" });
6898await updateTopicName(-100123, 42, { closed: true });
6999await expect(getTopicName(-100123, 42)).resolves.toBe("Deployments");
70-expect((await getTopicEntry(-100123, 42))?.closed).toBe(true);
100+expect(getStoredTopicEntry(stores, -100123, 42)?.closed).toBe(true);
71101});
7210273103it("marks topic as reopened", async () => {
74104await updateTopicName(-100123, 42, { name: "Deployments", closed: true });
75105await updateTopicName(-100123, 42, { closed: false });
76-expect((await getTopicEntry(-100123, 42))?.closed).toBe(false);
106+expect(getStoredTopicEntry(stores, -100123, 42)?.closed).toBe(false);
77107});
7810879109it("stores icon metadata", async () => {
@@ -82,24 +112,24 @@ describe("topic-name-cache", () => {
82112iconColor: 0x6fb9f0,
83113iconCustomEmojiId: "emoji123",
84114});
85-const entry = await getTopicEntry(-100123, 42);
115+const entry = getStoredTopicEntry(stores, -100123, 42);
86116expect(entry?.iconColor).toBe(0x6fb9f0);
87117expect(entry?.iconCustomEmojiId).toBe("emoji123");
88118});
8911990120it("does not store entries with empty name and no prior entry", async () => {
91121await updateTopicName(-100123, 42, { closed: true });
92122await expect(getTopicName(-100123, 42)).resolves.toBeUndefined();
93-expect(topicNameCacheSize()).toBe(0);
123+expect(topicStoreSize(stores)).toBe(0);
94124});
9512596126it("updates timestamps on write", async () => {
97127vi.useFakeTimers();
98128await updateTopicName(-100123, 42, { name: "A" });
99-const t1 = (await getTopicEntry(-100123, 42))?.updatedAt ?? 0;
129+const t1 = getStoredTopicEntry(stores, -100123, 42)?.updatedAt ?? 0;
100130await vi.advanceTimersByTimeAsync(10);
101131await updateTopicName(-100123, 42, { name: "B" });
102-const t2 = (await getTopicEntry(-100123, 42))?.updatedAt ?? 0;
132+const t2 = getStoredTopicEntry(stores, -100123, 42)?.updatedAt ?? 0;
103133expect(t2).toBeGreaterThan(t1);
104134});
105135@@ -112,7 +142,7 @@ describe("topic-name-cache", () => {
112142for (let i = 0; i < 2049; i++) {
113143await updateTopicName(-100000, i, { name: `Topic ${i}` });
114144}
115-expect(topicNameCacheSize()).toBe(2048);
145+expect(topicStoreSize(stores)).toBe(2048);
116146await expect(getTopicName(-100000, 0)).resolves.toBeUndefined();
117147await expect(getTopicName(-100000, 2048)).resolves.toBe("Topic 2048");
118148});
@@ -127,7 +157,7 @@ describe("topic-name-cache", () => {
127157await getTopicName(-100000, 1);
128158await updateTopicName(-100000, 9999, { name: "Newcomer" });
129159await expect(getTopicName(-100000, 1)).resolves.toBe("Active");
130-expect(topicNameCacheSize()).toBe(2048);
160+expect(topicStoreSize(stores)).toBe(2048);
131161});
132162133163it("reloads persisted entries from plugin state", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。