this repo has no description
1import { afterEach, describe, expect, mock, test } from "bun:test";
2import { cleanupUserCache, getUserInfo } from "./user-cache";
3
4describe("user-cache", () => {
5 const mockSlackClient = {
6 users: {
7 info: mock(async () => ({
8 user: {
9 name: "testuser",
10 real_name: "Test User",
11 },
12 })),
13 },
14 };
15
16 afterEach(() => {
17 cleanupUserCache();
18 mockSlackClient.users.info.mockClear();
19 mockSlackClient.users.info.mockReset();
20 });
21
22 describe("getUserInfo", () => {
23 test("uses display name from event if provided", async () => {
24 const client = {
25 users: {
26 info: mock(async () => ({
27 user: {
28 name: "testuser",
29 real_name: "Test User",
30 },
31 })),
32 },
33 };
34
35 const result = await getUserInfo("U123", client, "Event Display Name");
36
37 expect(result).toEqual({
38 name: "Event Display Name",
39 realName: "Event Display Name",
40 });
41 // Should not call API when display name provided
42 expect(client.users.info).toHaveBeenCalledTimes(0);
43 });
44
45 test("fetches user info from Slack on cache miss", async () => {
46 const client = {
47 users: {
48 info: mock(async () => ({
49 user: {
50 name: "testuser",
51 real_name: "Test User",
52 },
53 })),
54 },
55 };
56
57 const result = await getUserInfo("U125", client);
58
59 expect(result).toEqual({
60 name: "testuser",
61 realName: "Test User",
62 });
63 expect(client.users.info).toHaveBeenCalledTimes(1);
64 });
65
66 test("returns cached data on cache hit", async () => {
67 const client = {
68 users: {
69 info: mock(async () => ({
70 user: {
71 name: "testuser",
72 real_name: "Test User",
73 },
74 })),
75 },
76 };
77
78 // First call - cache miss
79 await getUserInfo("U124", client);
80 expect(client.users.info).toHaveBeenCalledTimes(1);
81
82 // Second call - cache hit
83 const result = await getUserInfo("U124", client);
84 expect(result).toEqual({
85 name: "testuser",
86 realName: "Test User",
87 });
88 expect(client.users.info).toHaveBeenCalledTimes(1); // Still 1
89 });
90
91 test("uses name as fallback for real_name", async () => {
92 const client = {
93 users: {
94 info: mock(async () => ({
95 user: {
96 name: "testuser",
97 },
98 })),
99 },
100 };
101
102 const result = await getUserInfo("U456", client);
103 expect(result).toEqual({
104 name: "testuser",
105 realName: "testuser",
106 });
107 });
108
109 test("handles missing user data gracefully", async () => {
110 const client = {
111 users: {
112 info: mock(async () => ({})),
113 },
114 };
115
116 const result = await getUserInfo("U789", client);
117 expect(result).toEqual({
118 name: "Unknown",
119 realName: "Unknown",
120 });
121 });
122
123 test("handles Slack API errors", async () => {
124 const client = {
125 users: {
126 info: mock(async () => {
127 throw new Error("API Error");
128 }),
129 },
130 };
131
132 const result = await getUserInfo("U999", client);
133 expect(result).toBeNull();
134 });
135
136 test("caches different users separately", async () => {
137 const client = {
138 users: {
139 info: mock(async ({ user }: { user: string }) => {
140 if (user === "U111") {
141 return { user: { name: "alice", real_name: "Alice" } };
142 }
143 return { user: { name: "bob", real_name: "Bob" } };
144 }),
145 },
146 };
147
148 const result1 = await getUserInfo("U111", client);
149 const result2 = await getUserInfo("U222", client);
150
151 expect(result1?.name).toBe("alice");
152 expect(result2?.name).toBe("bob");
153 expect(client.users.info).toHaveBeenCalledTimes(2);
154
155 // Both should be cached now
156 await getUserInfo("U111", client);
157 await getUserInfo("U222", client);
158 expect(client.users.info).toHaveBeenCalledTimes(2); // Still 2
159 });
160 });
161
162 describe("cleanupUserCache", () => {
163 test("cleanup runs without errors", () => {
164 // Just test that cleanup doesn't throw
165 expect(() => cleanupUserCache()).not.toThrow();
166 });
167 });
168});