this repo has no description
1import { afterEach, beforeEach, describe, expect, test } from "bun:test";
2import {
3 generateThreadId,
4 getThreadByThreadId,
5 isFirstThreadMessage,
6 updateThreadTimestamp,
7} from "./threads";
8import { threadTimestamps } from "./db";
9
10describe("threads", () => {
11 const testChannelId = "C123TEST";
12 const testThreadTs = "1234567890.123456";
13
14 afterEach(() => {
15 // Clean up test data
16 const thread = threadTimestamps.get(testThreadTs);
17 if (thread) {
18 threadTimestamps.cleanup(Date.now() + 1000);
19 }
20 });
21
22 describe("generateThreadId", () => {
23 test("generates a 5-character thread ID", () => {
24 const threadId = generateThreadId(testThreadTs);
25 expect(threadId).toBeString();
26 expect(threadId.length).toBe(5);
27 });
28
29 test("generates consistent IDs for same input", () => {
30 const id1 = generateThreadId(testThreadTs);
31 const id2 = generateThreadId(testThreadTs);
32 expect(id1).toBe(id2);
33 });
34
35 test("generates different IDs for different inputs", () => {
36 const id1 = generateThreadId("1234567890.123456");
37 const id2 = generateThreadId("9876543210.654321");
38 expect(id1).not.toBe(id2);
39 });
40
41 test("generates alphanumeric IDs", () => {
42 const threadId = generateThreadId(testThreadTs);
43 expect(threadId).toMatch(/^[a-z0-9]{5}$/);
44 });
45 });
46
47 describe("isFirstThreadMessage", () => {
48 test("returns true for new thread", () => {
49 const result = isFirstThreadMessage(testThreadTs);
50 expect(result).toBe(true);
51 });
52
53 test("returns false for existing thread", () => {
54 updateThreadTimestamp(testThreadTs, testChannelId);
55 const result = isFirstThreadMessage(testThreadTs);
56 expect(result).toBe(false);
57 });
58 });
59
60 describe("updateThreadTimestamp", () => {
61 test("creates new thread entry", () => {
62 const threadId = updateThreadTimestamp(testThreadTs, testChannelId);
63
64 expect(threadId).toBeString();
65 expect(threadId.length).toBe(5);
66
67 const thread = threadTimestamps.get(testThreadTs);
68 expect(thread).toBeDefined();
69 expect(thread?.thread_id).toBe(threadId);
70 expect(thread?.slack_channel_id).toBe(testChannelId);
71 });
72
73 test("updates existing thread timestamp", () => {
74 const threadId1 = updateThreadTimestamp(testThreadTs, testChannelId);
75 const thread1 = threadTimestamps.get(testThreadTs);
76 const timestamp1 = thread1?.last_message_time;
77
78 // Wait a bit to ensure timestamp changes
79 Bun.sleepSync(10);
80
81 const threadId2 = updateThreadTimestamp(testThreadTs, testChannelId);
82 const thread2 = threadTimestamps.get(testThreadTs);
83 const timestamp2 = thread2?.last_message_time;
84
85 expect(threadId1).toBe(threadId2);
86 expect(timestamp2).toBeGreaterThan(timestamp1!);
87 });
88 });
89
90 describe("getThreadByThreadId", () => {
91 test("retrieves thread by thread ID", () => {
92 const threadId = updateThreadTimestamp(testThreadTs, testChannelId);
93 const thread = getThreadByThreadId(threadId);
94
95 expect(thread).toBeDefined();
96 expect(thread?.thread_ts).toBe(testThreadTs);
97 expect(thread?.thread_id).toBe(threadId);
98 expect(thread?.slack_channel_id).toBe(testChannelId);
99 });
100
101 test("returns null for non-existent thread ID", () => {
102 const thread = getThreadByThreadId("xxxxx");
103 expect(thread).toBeNull();
104 });
105 });
106});