@herdctl/discord 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/dist/__tests__/auto-mode-handler.test.d.ts +2 -0
  2. package/dist/__tests__/auto-mode-handler.test.d.ts.map +1 -0
  3. package/dist/__tests__/auto-mode-handler.test.js +362 -0
  4. package/dist/__tests__/auto-mode-handler.test.js.map +1 -0
  5. package/dist/__tests__/discord-connector.test.d.ts +2 -0
  6. package/dist/__tests__/discord-connector.test.d.ts.map +1 -0
  7. package/dist/__tests__/discord-connector.test.js +958 -0
  8. package/dist/__tests__/discord-connector.test.js.map +1 -0
  9. package/dist/__tests__/error-handler.test.d.ts +2 -0
  10. package/dist/__tests__/error-handler.test.d.ts.map +1 -0
  11. package/dist/__tests__/error-handler.test.js +509 -0
  12. package/dist/__tests__/error-handler.test.js.map +1 -0
  13. package/dist/__tests__/errors.test.d.ts +2 -0
  14. package/dist/__tests__/errors.test.d.ts.map +1 -0
  15. package/dist/__tests__/errors.test.js +152 -0
  16. package/dist/__tests__/errors.test.js.map +1 -0
  17. package/dist/__tests__/logger.test.d.ts +2 -0
  18. package/dist/__tests__/logger.test.d.ts.map +1 -0
  19. package/dist/__tests__/logger.test.js +282 -0
  20. package/dist/__tests__/logger.test.js.map +1 -0
  21. package/dist/__tests__/mention-handler.test.d.ts +2 -0
  22. package/dist/__tests__/mention-handler.test.d.ts.map +1 -0
  23. package/dist/__tests__/mention-handler.test.js +547 -0
  24. package/dist/__tests__/mention-handler.test.js.map +1 -0
  25. package/dist/auto-mode-handler.d.ts +145 -0
  26. package/dist/auto-mode-handler.d.ts.map +1 -0
  27. package/dist/auto-mode-handler.js +211 -0
  28. package/dist/auto-mode-handler.js.map +1 -0
  29. package/dist/commands/__tests__/command-manager.test.d.ts +2 -0
  30. package/dist/commands/__tests__/command-manager.test.d.ts.map +1 -0
  31. package/dist/commands/__tests__/command-manager.test.js +307 -0
  32. package/dist/commands/__tests__/command-manager.test.js.map +1 -0
  33. package/dist/commands/__tests__/help.test.d.ts +2 -0
  34. package/dist/commands/__tests__/help.test.d.ts.map +1 -0
  35. package/dist/commands/__tests__/help.test.js +105 -0
  36. package/dist/commands/__tests__/help.test.js.map +1 -0
  37. package/dist/commands/__tests__/reset.test.d.ts +2 -0
  38. package/dist/commands/__tests__/reset.test.d.ts.map +1 -0
  39. package/dist/commands/__tests__/reset.test.js +140 -0
  40. package/dist/commands/__tests__/reset.test.js.map +1 -0
  41. package/dist/commands/__tests__/status.test.d.ts +2 -0
  42. package/dist/commands/__tests__/status.test.d.ts.map +1 -0
  43. package/dist/commands/__tests__/status.test.js +205 -0
  44. package/dist/commands/__tests__/status.test.js.map +1 -0
  45. package/dist/commands/command-manager.d.ts +66 -0
  46. package/dist/commands/command-manager.d.ts.map +1 -0
  47. package/dist/commands/command-manager.js +191 -0
  48. package/dist/commands/command-manager.js.map +1 -0
  49. package/dist/commands/help.d.ts +8 -0
  50. package/dist/commands/help.d.ts.map +1 -0
  51. package/dist/commands/help.js +27 -0
  52. package/dist/commands/help.js.map +1 -0
  53. package/dist/commands/index.d.ts +12 -0
  54. package/dist/commands/index.d.ts.map +1 -0
  55. package/dist/commands/index.js +13 -0
  56. package/dist/commands/index.js.map +1 -0
  57. package/dist/commands/reset.d.ts +9 -0
  58. package/dist/commands/reset.d.ts.map +1 -0
  59. package/dist/commands/reset.js +28 -0
  60. package/dist/commands/reset.js.map +1 -0
  61. package/dist/commands/status.d.ts +9 -0
  62. package/dist/commands/status.d.ts.map +1 -0
  63. package/dist/commands/status.js +102 -0
  64. package/dist/commands/status.js.map +1 -0
  65. package/dist/commands/types.d.ts +87 -0
  66. package/dist/commands/types.d.ts.map +1 -0
  67. package/dist/commands/types.js +8 -0
  68. package/dist/commands/types.js.map +1 -0
  69. package/dist/discord-connector.d.ts +154 -0
  70. package/dist/discord-connector.d.ts.map +1 -0
  71. package/dist/discord-connector.js +638 -0
  72. package/dist/discord-connector.js.map +1 -0
  73. package/dist/error-handler.d.ts +237 -0
  74. package/dist/error-handler.d.ts.map +1 -0
  75. package/dist/error-handler.js +433 -0
  76. package/dist/error-handler.js.map +1 -0
  77. package/dist/errors.d.ts +61 -0
  78. package/dist/errors.d.ts.map +1 -0
  79. package/dist/errors.js +77 -0
  80. package/dist/errors.js.map +1 -0
  81. package/dist/index.d.ts +34 -0
  82. package/dist/index.d.ts.map +1 -0
  83. package/dist/index.js +36 -0
  84. package/dist/index.js.map +1 -0
  85. package/dist/logger.d.ts +119 -0
  86. package/dist/logger.d.ts.map +1 -0
  87. package/dist/logger.js +198 -0
  88. package/dist/logger.js.map +1 -0
  89. package/dist/mention-handler.d.ts +176 -0
  90. package/dist/mention-handler.d.ts.map +1 -0
  91. package/dist/mention-handler.js +236 -0
  92. package/dist/mention-handler.js.map +1 -0
  93. package/dist/session-manager/__tests__/errors.test.d.ts +2 -0
  94. package/dist/session-manager/__tests__/errors.test.d.ts.map +1 -0
  95. package/dist/session-manager/__tests__/errors.test.js +124 -0
  96. package/dist/session-manager/__tests__/errors.test.js.map +1 -0
  97. package/dist/session-manager/__tests__/session-manager.test.d.ts +2 -0
  98. package/dist/session-manager/__tests__/session-manager.test.d.ts.map +1 -0
  99. package/dist/session-manager/__tests__/session-manager.test.js +517 -0
  100. package/dist/session-manager/__tests__/session-manager.test.js.map +1 -0
  101. package/dist/session-manager/__tests__/types.test.d.ts +2 -0
  102. package/dist/session-manager/__tests__/types.test.d.ts.map +1 -0
  103. package/dist/session-manager/__tests__/types.test.js +169 -0
  104. package/dist/session-manager/__tests__/types.test.js.map +1 -0
  105. package/dist/session-manager/errors.d.ts +58 -0
  106. package/dist/session-manager/errors.d.ts.map +1 -0
  107. package/dist/session-manager/errors.js +70 -0
  108. package/dist/session-manager/errors.js.map +1 -0
  109. package/dist/session-manager/index.d.ts +11 -0
  110. package/dist/session-manager/index.d.ts.map +1 -0
  111. package/dist/session-manager/index.js +12 -0
  112. package/dist/session-manager/index.js.map +1 -0
  113. package/dist/session-manager/session-manager.d.ts +107 -0
  114. package/dist/session-manager/session-manager.d.ts.map +1 -0
  115. package/dist/session-manager/session-manager.js +347 -0
  116. package/dist/session-manager/session-manager.js.map +1 -0
  117. package/dist/session-manager/types.d.ts +167 -0
  118. package/dist/session-manager/types.d.ts.map +1 -0
  119. package/dist/session-manager/types.js +57 -0
  120. package/dist/session-manager/types.js.map +1 -0
  121. package/dist/types.d.ts +323 -0
  122. package/dist/types.d.ts.map +1 -0
  123. package/dist/types.js +8 -0
  124. package/dist/types.js.map +1 -0
  125. package/dist/utils/__tests__/formatting.test.d.ts +2 -0
  126. package/dist/utils/__tests__/formatting.test.d.ts.map +1 -0
  127. package/dist/utils/__tests__/formatting.test.js +571 -0
  128. package/dist/utils/__tests__/formatting.test.js.map +1 -0
  129. package/dist/utils/formatting.d.ts +211 -0
  130. package/dist/utils/formatting.d.ts.map +1 -0
  131. package/dist/utils/formatting.js +305 -0
  132. package/dist/utils/formatting.js.map +1 -0
  133. package/dist/utils/index.d.ts +5 -0
  134. package/dist/utils/index.d.ts.map +1 -0
  135. package/dist/utils/index.js +9 -0
  136. package/dist/utils/index.js.map +1 -0
  137. package/package.json +49 -0
@@ -0,0 +1,571 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import { DISCORD_MAX_MESSAGE_LENGTH, DEFAULT_MESSAGE_DELAY_MS, MIN_CHUNK_SIZE, findSplitPoint, splitMessage, needsSplit, startTypingIndicator, sendSplitMessage, sendWithTyping, truncateMessage, formatCodeBlock, escapeMarkdown, } from "../formatting.js";
3
+ function createMockChannel() {
4
+ return {
5
+ id: "channel-123",
6
+ send: vi.fn().mockResolvedValue({ id: "message-id" }),
7
+ sendTyping: vi.fn().mockResolvedValue(undefined),
8
+ };
9
+ }
10
+ // =============================================================================
11
+ // Constants Tests
12
+ // =============================================================================
13
+ describe("constants", () => {
14
+ it("exports correct Discord message limit", () => {
15
+ expect(DISCORD_MAX_MESSAGE_LENGTH).toBe(2000);
16
+ });
17
+ it("exports correct default message delay", () => {
18
+ expect(DEFAULT_MESSAGE_DELAY_MS).toBe(500);
19
+ });
20
+ it("exports correct minimum chunk size", () => {
21
+ expect(MIN_CHUNK_SIZE).toBe(100);
22
+ });
23
+ });
24
+ // =============================================================================
25
+ // findSplitPoint Tests
26
+ // =============================================================================
27
+ describe("findSplitPoint", () => {
28
+ it("returns text length when text fits within maxLength", () => {
29
+ const text = "Short message";
30
+ expect(findSplitPoint(text, 100)).toBe(text.length);
31
+ });
32
+ it("splits at paragraph break when available", () => {
33
+ // Use a long enough first section to satisfy MIN_CHUNK_SIZE (>100 chars)
34
+ const firstPart = "This is the first paragraph with enough content that exceeds the minimum chunk size requirement of one hundred.";
35
+ const secondPart = "Second paragraph that continues with more content here.";
36
+ const text = `${firstPart}\n\n${secondPart}`;
37
+ // maxLength must include the paragraph break position
38
+ const splitIndex = findSplitPoint(text, firstPart.length + 5);
39
+ expect(text.slice(0, splitIndex).trim()).toBe(firstPart);
40
+ });
41
+ it("splits at newline when no paragraph break available", () => {
42
+ // Use a long enough first line to satisfy MIN_CHUNK_SIZE (100 chars)
43
+ // First line must be > 100 chars so the newline split point is valid
44
+ const firstLine = "This is the first line with content that is definitely long enough to exceed one hundred characters minimum.";
45
+ const secondLine = "Second line is much longer than this and continues with more text.";
46
+ const text = `${firstLine}\n${secondLine}`;
47
+ // maxLength must include the newline position
48
+ const splitIndex = findSplitPoint(text, firstLine.length + 5);
49
+ expect(text.slice(0, splitIndex).trim()).toBe(firstLine);
50
+ });
51
+ it("splits at sentence end when no newline available", () => {
52
+ // Use a long enough first sentence to satisfy MIN_CHUNK_SIZE
53
+ const firstSentence = "This is the first sentence with enough content to exceed the minimum chunk size of one hundred characters.";
54
+ const secondSentence = " Second sentence continues on and is much longer with additional content.";
55
+ const text = firstSentence + secondSentence;
56
+ const splitIndex = findSplitPoint(text, 130);
57
+ expect(text.slice(0, splitIndex).trim()).toBe(firstSentence);
58
+ });
59
+ it("splits at comma when no sentence boundary available", () => {
60
+ // Use a long enough first clause to satisfy MIN_CHUNK_SIZE
61
+ const firstClause = "This is a long clause that has enough content to exceed the minimum chunk size requirement for splitting,";
62
+ const secondClause = " and here is another part that makes it even longer with more content.";
63
+ const text = firstClause + secondClause;
64
+ const splitIndex = findSplitPoint(text, 120);
65
+ expect(text.slice(0, splitIndex).trim()).toBe(firstClause);
66
+ });
67
+ it("splits at space when no other boundary available", () => {
68
+ // Use enough words to have a split point above MIN_CHUNK_SIZE
69
+ const text = ("word " + "x".repeat(20) + " ").repeat(20);
70
+ const splitIndex = findSplitPoint(text, 150);
71
+ // Should find a space to split at within the limit
72
+ expect(splitIndex).toBeLessThanOrEqual(150);
73
+ expect(splitIndex).toBeGreaterThan(MIN_CHUNK_SIZE);
74
+ });
75
+ it("respects minimum chunk size", () => {
76
+ // Even if there's a split point early, don't use it if it's too short
77
+ const text = ". " + "a".repeat(200);
78
+ const splitIndex = findSplitPoint(text, 150);
79
+ // Should not split at position 2 because that's below MIN_CHUNK_SIZE
80
+ expect(splitIndex).toBeGreaterThan(MIN_CHUNK_SIZE);
81
+ });
82
+ it("falls back to maxLength when no good split point found", () => {
83
+ // Long string with no spaces or split points
84
+ const text = "a".repeat(300);
85
+ const splitIndex = findSplitPoint(text, 200);
86
+ expect(splitIndex).toBe(200);
87
+ });
88
+ it("uses custom split points when provided", () => {
89
+ // Use a long enough section to satisfy MIN_CHUNK_SIZE
90
+ const text = "a".repeat(110) + "|" + "b".repeat(100);
91
+ const splitIndex = findSplitPoint(text, 150, ["|"]);
92
+ expect(text.slice(0, splitIndex)).toBe("a".repeat(110) + "|");
93
+ });
94
+ });
95
+ // =============================================================================
96
+ // splitMessage Tests
97
+ // =============================================================================
98
+ describe("splitMessage", () => {
99
+ it("returns single chunk for short messages", () => {
100
+ const content = "This is a short message";
101
+ const result = splitMessage(content);
102
+ expect(result.chunks).toHaveLength(1);
103
+ expect(result.chunks[0]).toBe(content);
104
+ expect(result.wasSplit).toBe(false);
105
+ expect(result.originalLength).toBe(content.length);
106
+ });
107
+ it("splits long messages into multiple chunks", () => {
108
+ const content = "a".repeat(3000);
109
+ const result = splitMessage(content);
110
+ expect(result.chunks.length).toBeGreaterThan(1);
111
+ expect(result.wasSplit).toBe(true);
112
+ expect(result.originalLength).toBe(3000);
113
+ });
114
+ it("respects custom maxLength", () => {
115
+ const content = "a".repeat(500);
116
+ const result = splitMessage(content, { maxLength: 100 });
117
+ expect(result.chunks.length).toBe(5);
118
+ result.chunks.forEach((chunk) => {
119
+ expect(chunk.length).toBeLessThanOrEqual(100);
120
+ });
121
+ });
122
+ it("preserves sentence boundaries by default", () => {
123
+ // Use long enough sentences to satisfy MIN_CHUNK_SIZE
124
+ const sentence1 = "This is the first sentence with enough content to exceed the minimum chunk size requirement for splitting.";
125
+ const sentence2 = " This is the second sentence that continues with more content to make it longer.";
126
+ const content = sentence1 + sentence2;
127
+ const result = splitMessage(content, { maxLength: 130 });
128
+ expect(result.chunks[0]).toBe(sentence1);
129
+ expect(result.chunks[1].trim()).toBe(sentence2.trim());
130
+ });
131
+ it("does not preserve boundaries when disabled", () => {
132
+ const content = "Short. " + "a".repeat(100);
133
+ const result = splitMessage(content, {
134
+ maxLength: 50,
135
+ preserveBoundaries: false,
136
+ });
137
+ // Without boundary preservation, it just cuts at maxLength
138
+ expect(result.chunks[0].length).toBe(50);
139
+ });
140
+ it("trims whitespace from chunks", () => {
141
+ const content = "First part. \n\n Second part.";
142
+ const result = splitMessage(content, { maxLength: 20 });
143
+ result.chunks.forEach((chunk) => {
144
+ expect(chunk).toBe(chunk.trim());
145
+ });
146
+ });
147
+ it("handles content with only whitespace", () => {
148
+ const content = " ";
149
+ const result = splitMessage(content);
150
+ // Whitespace-only content returns as-is (not split, fits in one message)
151
+ expect(result.chunks).toHaveLength(1);
152
+ expect(result.chunks[0]).toBe(" ");
153
+ expect(result.wasSplit).toBe(false);
154
+ });
155
+ it("handles empty content", () => {
156
+ const content = "";
157
+ const result = splitMessage(content);
158
+ expect(result.chunks).toHaveLength(1);
159
+ expect(result.chunks[0]).toBe("");
160
+ expect(result.wasSplit).toBe(false);
161
+ });
162
+ it("splits at paragraph breaks preferentially", () => {
163
+ // Use long enough paragraphs to satisfy MIN_CHUNK_SIZE
164
+ const para1 = "First paragraph with enough content to exceed the minimum chunk size requirement for the splitting algorithm.";
165
+ const para2 = "Second paragraph that also has enough content to be considered a proper chunk in the split.";
166
+ const content = `${para1}\n\n${para2}`;
167
+ const result = splitMessage(content, { maxLength: 130 });
168
+ expect(result.chunks[0]).toBe(para1);
169
+ expect(result.chunks[1]).toBe(para2);
170
+ });
171
+ it("handles very long single word gracefully", () => {
172
+ const longWord = "supercalifragilisticexpialidocious".repeat(100);
173
+ const result = splitMessage(longWord, { maxLength: 100 });
174
+ expect(result.wasSplit).toBe(true);
175
+ // Each chunk should be at most maxLength
176
+ result.chunks.forEach((chunk) => {
177
+ expect(chunk.length).toBeLessThanOrEqual(100);
178
+ });
179
+ });
180
+ it("combines content from all chunks equals original (minus whitespace)", () => {
181
+ const content = "Part one. Part two. Part three. Part four.";
182
+ const result = splitMessage(content, { maxLength: 15 });
183
+ const combined = result.chunks.join(" ");
184
+ // The combined content should contain all the words
185
+ expect(combined.replace(/\s+/g, " ")).toContain("Part one");
186
+ expect(combined.replace(/\s+/g, " ")).toContain("Part four");
187
+ });
188
+ });
189
+ // =============================================================================
190
+ // needsSplit Tests
191
+ // =============================================================================
192
+ describe("needsSplit", () => {
193
+ it("returns false for messages under limit", () => {
194
+ expect(needsSplit("Short message")).toBe(false);
195
+ });
196
+ it("returns false for messages at exactly the limit", () => {
197
+ const content = "a".repeat(2000);
198
+ expect(needsSplit(content)).toBe(false);
199
+ });
200
+ it("returns true for messages over the limit", () => {
201
+ const content = "a".repeat(2001);
202
+ expect(needsSplit(content)).toBe(true);
203
+ });
204
+ it("respects custom maxLength", () => {
205
+ expect(needsSplit("12345", 5)).toBe(false);
206
+ expect(needsSplit("123456", 5)).toBe(true);
207
+ });
208
+ });
209
+ // =============================================================================
210
+ // startTypingIndicator Tests
211
+ // =============================================================================
212
+ describe("startTypingIndicator", () => {
213
+ beforeEach(() => {
214
+ vi.useFakeTimers();
215
+ });
216
+ afterEach(() => {
217
+ vi.useRealTimers();
218
+ });
219
+ it("sends initial typing indicator", () => {
220
+ const channel = createMockChannel();
221
+ const controller = startTypingIndicator(channel);
222
+ expect(channel.sendTyping).toHaveBeenCalledTimes(1);
223
+ controller.stop();
224
+ });
225
+ it("refreshes typing indicator at interval", () => {
226
+ const channel = createMockChannel();
227
+ const controller = startTypingIndicator(channel, 1000);
228
+ // Initial call
229
+ expect(channel.sendTyping).toHaveBeenCalledTimes(1);
230
+ // After 1 second
231
+ vi.advanceTimersByTime(1000);
232
+ expect(channel.sendTyping).toHaveBeenCalledTimes(2);
233
+ // After another second
234
+ vi.advanceTimersByTime(1000);
235
+ expect(channel.sendTyping).toHaveBeenCalledTimes(3);
236
+ controller.stop();
237
+ });
238
+ it("stops refreshing when stop() is called", () => {
239
+ const channel = createMockChannel();
240
+ const controller = startTypingIndicator(channel, 1000);
241
+ // Initial call
242
+ expect(channel.sendTyping).toHaveBeenCalledTimes(1);
243
+ // Stop the typing indicator
244
+ controller.stop();
245
+ // Advance time - should not call sendTyping again
246
+ vi.advanceTimersByTime(5000);
247
+ expect(channel.sendTyping).toHaveBeenCalledTimes(1);
248
+ });
249
+ it("reports isActive correctly", () => {
250
+ const channel = createMockChannel();
251
+ const controller = startTypingIndicator(channel);
252
+ expect(controller.isActive).toBe(true);
253
+ controller.stop();
254
+ expect(controller.isActive).toBe(false);
255
+ });
256
+ it("handles sendTyping errors gracefully", () => {
257
+ const channel = createMockChannel();
258
+ channel.sendTyping = vi.fn().mockRejectedValue(new Error("Network error"));
259
+ // Should not throw
260
+ const controller = startTypingIndicator(channel);
261
+ expect(controller.isActive).toBe(true);
262
+ controller.stop();
263
+ });
264
+ it("uses default refresh interval of 5000ms", () => {
265
+ const channel = createMockChannel();
266
+ const controller = startTypingIndicator(channel);
267
+ // Initial call
268
+ expect(channel.sendTyping).toHaveBeenCalledTimes(1);
269
+ // After 4999ms - should not have refreshed yet
270
+ vi.advanceTimersByTime(4999);
271
+ expect(channel.sendTyping).toHaveBeenCalledTimes(1);
272
+ // After 5000ms total - should have refreshed
273
+ vi.advanceTimersByTime(1);
274
+ expect(channel.sendTyping).toHaveBeenCalledTimes(2);
275
+ controller.stop();
276
+ });
277
+ });
278
+ // =============================================================================
279
+ // sendSplitMessage Tests
280
+ // =============================================================================
281
+ describe("sendSplitMessage", () => {
282
+ beforeEach(() => {
283
+ vi.useFakeTimers();
284
+ });
285
+ afterEach(() => {
286
+ vi.useRealTimers();
287
+ });
288
+ it("sends a single message for short content", async () => {
289
+ const channel = createMockChannel();
290
+ channel.send = vi.fn().mockResolvedValue({ id: "msg-1" });
291
+ const promise = sendSplitMessage(channel, "Short message");
292
+ await vi.runAllTimersAsync();
293
+ const result = await promise;
294
+ expect(channel.send).toHaveBeenCalledTimes(1);
295
+ expect(channel.send).toHaveBeenCalledWith("Short message");
296
+ expect(result).toEqual(["msg-1"]);
297
+ });
298
+ it("sends multiple messages for long content", async () => {
299
+ const channel = createMockChannel();
300
+ let messageCount = 0;
301
+ channel.send = vi.fn().mockImplementation(() => {
302
+ messageCount++;
303
+ return Promise.resolve({ id: `msg-${messageCount}` });
304
+ });
305
+ const content = "a".repeat(3000);
306
+ const promise = sendSplitMessage(channel, content);
307
+ await vi.runAllTimersAsync();
308
+ const result = await promise;
309
+ expect(channel.send).toHaveBeenCalledTimes(2);
310
+ expect(result).toHaveLength(2);
311
+ });
312
+ it("adds delay between messages", async () => {
313
+ const channel = createMockChannel();
314
+ const sendTimes = [];
315
+ channel.send = vi.fn().mockImplementation(() => {
316
+ sendTimes.push(Date.now());
317
+ return Promise.resolve({ id: "msg" });
318
+ });
319
+ const content = "First part. " + "a".repeat(2000);
320
+ const promise = sendSplitMessage(channel, content, { delayMs: 1000 });
321
+ // First message should be sent immediately
322
+ await vi.advanceTimersByTimeAsync(0);
323
+ expect(sendTimes.length).toBeGreaterThanOrEqual(1);
324
+ // Complete all timers
325
+ await vi.runAllTimersAsync();
326
+ await promise;
327
+ // Should have sent multiple messages
328
+ expect(channel.send).toHaveBeenCalledTimes(2);
329
+ });
330
+ it("respects custom delay", async () => {
331
+ const channel = createMockChannel();
332
+ channel.send = vi.fn().mockResolvedValue({ id: "msg" });
333
+ const content = "First. " + "a".repeat(2000);
334
+ const promise = sendSplitMessage(channel, content, {
335
+ delayMs: 200,
336
+ maxLength: 100,
337
+ });
338
+ await vi.runAllTimersAsync();
339
+ await promise;
340
+ // Multiple messages should have been sent
341
+ expect(channel.send.mock.calls.length).toBeGreaterThan(1);
342
+ });
343
+ it("passes split options through", async () => {
344
+ const channel = createMockChannel();
345
+ channel.send = vi.fn().mockResolvedValue({ id: "msg" });
346
+ const content = "a".repeat(500);
347
+ const promise = sendSplitMessage(channel, content, { maxLength: 100 });
348
+ await vi.runAllTimersAsync();
349
+ await promise;
350
+ // Should split into 5 messages
351
+ expect(channel.send).toHaveBeenCalledTimes(5);
352
+ });
353
+ });
354
+ // =============================================================================
355
+ // sendWithTyping Tests
356
+ // =============================================================================
357
+ describe("sendWithTyping", () => {
358
+ beforeEach(() => {
359
+ vi.useFakeTimers();
360
+ });
361
+ afterEach(() => {
362
+ vi.useRealTimers();
363
+ });
364
+ it("shows typing indicator while processing", async () => {
365
+ const channel = createMockChannel();
366
+ channel.send = vi.fn().mockResolvedValue({ id: "msg-1" });
367
+ const contentProvider = vi.fn().mockResolvedValue("Response content");
368
+ const promise = sendWithTyping(channel, contentProvider);
369
+ // Typing indicator should be started
370
+ expect(channel.sendTyping).toHaveBeenCalled();
371
+ await vi.runAllTimersAsync();
372
+ await promise;
373
+ });
374
+ it("sends the content from contentProvider", async () => {
375
+ const channel = createMockChannel();
376
+ channel.send = vi.fn().mockResolvedValue({ id: "msg-1" });
377
+ const contentProvider = vi.fn().mockResolvedValue("Generated content");
378
+ const promise = sendWithTyping(channel, contentProvider);
379
+ await vi.runAllTimersAsync();
380
+ await promise;
381
+ expect(contentProvider).toHaveBeenCalled();
382
+ expect(channel.send).toHaveBeenCalledWith("Generated content");
383
+ });
384
+ it("stops typing indicator after sending", async () => {
385
+ const channel = createMockChannel();
386
+ channel.send = vi.fn().mockResolvedValue({ id: "msg-1" });
387
+ const contentProvider = vi.fn().mockResolvedValue("Content");
388
+ const promise = sendWithTyping(channel, contentProvider);
389
+ await vi.runAllTimersAsync();
390
+ await promise;
391
+ // Advance more time - typing should have stopped
392
+ const callCountAfterSend = channel.sendTyping.mock.calls.length;
393
+ vi.advanceTimersByTime(10000);
394
+ // Should not have sent more typing indicators
395
+ expect(channel.sendTyping.mock.calls.length).toBe(callCountAfterSend);
396
+ });
397
+ it("stops typing indicator on error", async () => {
398
+ const channel = createMockChannel();
399
+ const contentProvider = vi
400
+ .fn()
401
+ .mockRejectedValue(new Error("Processing failed"));
402
+ // Start the operation (will fail) - need to catch the rejection
403
+ let caughtError = null;
404
+ const promise = sendWithTyping(channel, contentProvider).catch((err) => {
405
+ caughtError = err;
406
+ });
407
+ // Run timers and wait for the promise to settle
408
+ await vi.runAllTimersAsync();
409
+ await promise;
410
+ // Verify error was caught
411
+ expect(caughtError).toBeInstanceOf(Error);
412
+ expect(caughtError.message).toBe("Processing failed");
413
+ // Typing should have stopped - save current count
414
+ const callCountAfterError = channel.sendTyping.mock.calls.length;
415
+ // Advance time to verify no more typing calls happen
416
+ await vi.advanceTimersByTimeAsync(10000);
417
+ expect(channel.sendTyping.mock.calls.length).toBe(callCountAfterError);
418
+ });
419
+ it("returns message IDs from sent messages", async () => {
420
+ const channel = createMockChannel();
421
+ channel.send = vi.fn().mockResolvedValue({ id: "msg-123" });
422
+ const contentProvider = vi.fn().mockResolvedValue("Short");
423
+ const promise = sendWithTyping(channel, contentProvider);
424
+ await vi.runAllTimersAsync();
425
+ const result = await promise;
426
+ expect(result).toEqual(["msg-123"]);
427
+ });
428
+ });
429
+ // =============================================================================
430
+ // truncateMessage Tests
431
+ // =============================================================================
432
+ describe("truncateMessage", () => {
433
+ it("returns message unchanged if under limit", () => {
434
+ const content = "Short message";
435
+ expect(truncateMessage(content)).toBe(content);
436
+ });
437
+ it("returns message unchanged if exactly at limit", () => {
438
+ const content = "a".repeat(2000);
439
+ expect(truncateMessage(content)).toBe(content);
440
+ });
441
+ it("truncates and adds ellipsis for long messages", () => {
442
+ const content = "a".repeat(2010);
443
+ const result = truncateMessage(content);
444
+ expect(result.length).toBe(2000);
445
+ expect(result.endsWith("...")).toBe(true);
446
+ });
447
+ it("respects custom maxLength", () => {
448
+ const content = "This is a test message";
449
+ const result = truncateMessage(content, 10);
450
+ expect(result.length).toBe(10);
451
+ expect(result).toBe("This is...");
452
+ });
453
+ it("uses custom ellipsis", () => {
454
+ const content = "This is a test message";
455
+ const result = truncateMessage(content, 12, "…");
456
+ expect(result.length).toBe(12);
457
+ expect(result.endsWith("…")).toBe(true);
458
+ });
459
+ });
460
+ // =============================================================================
461
+ // formatCodeBlock Tests
462
+ // =============================================================================
463
+ describe("formatCodeBlock", () => {
464
+ it("formats code without language tag", () => {
465
+ const code = 'const x = 1;';
466
+ const result = formatCodeBlock(code);
467
+ expect(result).toBe('```\nconst x = 1;\n```');
468
+ });
469
+ it("formats code with language tag", () => {
470
+ const code = 'const x: number = 1;';
471
+ const result = formatCodeBlock(code, 'typescript');
472
+ expect(result).toBe('```typescript\nconst x: number = 1;\n```');
473
+ });
474
+ it("handles multiline code", () => {
475
+ const code = 'function test() {\n return true;\n}';
476
+ const result = formatCodeBlock(code, 'javascript');
477
+ expect(result).toBe('```javascript\nfunction test() {\n return true;\n}\n```');
478
+ });
479
+ it("handles empty code", () => {
480
+ const result = formatCodeBlock('');
481
+ expect(result).toBe('```\n\n```');
482
+ });
483
+ });
484
+ // =============================================================================
485
+ // escapeMarkdown Tests
486
+ // =============================================================================
487
+ describe("escapeMarkdown", () => {
488
+ it("escapes asterisks", () => {
489
+ expect(escapeMarkdown("*bold*")).toBe("\\*bold\\*");
490
+ });
491
+ it("escapes underscores", () => {
492
+ expect(escapeMarkdown("_italic_")).toBe("\\_italic\\_");
493
+ });
494
+ it("escapes tildes", () => {
495
+ expect(escapeMarkdown("~~strike~~")).toBe("\\~\\~strike\\~\\~");
496
+ });
497
+ it("escapes backticks", () => {
498
+ expect(escapeMarkdown("`code`")).toBe("\\`code\\`");
499
+ });
500
+ it("escapes pipes", () => {
501
+ expect(escapeMarkdown("a|b")).toBe("a\\|b");
502
+ });
503
+ it("escapes backslashes", () => {
504
+ expect(escapeMarkdown("a\\b")).toBe("a\\\\b");
505
+ });
506
+ it("escapes multiple characters", () => {
507
+ expect(escapeMarkdown("*_~`|\\")).toBe("\\*\\_\\~\\`\\|\\\\");
508
+ });
509
+ it("leaves normal text unchanged", () => {
510
+ expect(escapeMarkdown("Hello world!")).toBe("Hello world!");
511
+ });
512
+ });
513
+ // =============================================================================
514
+ // Integration Tests
515
+ // =============================================================================
516
+ describe("integration", () => {
517
+ beforeEach(() => {
518
+ vi.useFakeTimers();
519
+ });
520
+ afterEach(() => {
521
+ vi.useRealTimers();
522
+ });
523
+ it("handles a realistic long response scenario", async () => {
524
+ const channel = createMockChannel();
525
+ const messageIds = [];
526
+ let msgCounter = 0;
527
+ channel.send = vi.fn().mockImplementation(() => {
528
+ msgCounter++;
529
+ messageIds.push(`msg-${msgCounter}`);
530
+ return Promise.resolve({ id: `msg-${msgCounter}` });
531
+ });
532
+ // Simulate a long Claude response with multiple paragraphs
533
+ const response = `
534
+ Here's how you can implement the feature:
535
+
536
+ First, create a new file called handler.ts and add the following code:
537
+
538
+ \`\`\`typescript
539
+ export function handleRequest(req: Request) {
540
+ const data = parseInput(req.body);
541
+ return processData(data);
542
+ }
543
+ \`\`\`
544
+
545
+ This function takes a request, parses the input, and processes the data.
546
+
547
+ Next, you'll need to update your router to use this handler. Add the following to your routes.ts file:
548
+
549
+ \`\`\`typescript
550
+ router.post('/api/data', handleRequest);
551
+ \`\`\`
552
+
553
+ Finally, make sure to add proper error handling. You can wrap the handler in a try-catch block or use middleware for global error handling.
554
+
555
+ Let me know if you have any questions about the implementation!
556
+ `.repeat(3); // Make it long enough to split
557
+ const promise = sendWithTyping(channel, async () => response, { delayMs: 100 });
558
+ await vi.runAllTimersAsync();
559
+ const result = await promise;
560
+ // Should have sent multiple messages
561
+ expect(result.length).toBeGreaterThan(1);
562
+ // All messages should be under the limit
563
+ const sentContents = channel.send.mock.calls.map((call) => call[0]);
564
+ sentContents.forEach((content) => {
565
+ expect(content.length).toBeLessThanOrEqual(DISCORD_MAX_MESSAGE_LENGTH);
566
+ });
567
+ // Typing indicator should have been started
568
+ expect(channel.sendTyping).toHaveBeenCalled();
569
+ });
570
+ });
571
+ //# sourceMappingURL=formatting.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatting.test.js","sourceRoot":"","sources":["../../../src/utils/__tests__/formatting.test.ts"],"names":[],"mappings":"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"}