diff --git a/src/services/slack/index.ts b/src/services/slack/index.ts index e1471e5990..39a7dd13a3 100644 --- a/src/services/slack/index.ts +++ b/src/services/slack/index.ts @@ -2,6 +2,7 @@ import * as vscode from 'vscode' let isSlackEnabled = false let webhookUrl = '' +let messageCount = 0 /** * Set slack notification configuration @@ -9,6 +10,9 @@ let webhookUrl = '' */ export const setSlackEnabled = (enabled: boolean): void => { isSlackEnabled = enabled + if (!enabled) { + messageCount = 0 + } } /** @@ -19,6 +23,14 @@ export const setWebhookUrl = (url: string): void => { webhookUrl = url } +/** + * Reset the message counter + * This is useful for starting a new sequence + */ +export const resetThread = (): void => { + messageCount = 0 +} + /** * Send a slack message * @param text string @@ -34,12 +46,16 @@ export const sendSlackMessage = async (text: string): Promise => { return } + // For subsequent messages, add a visual indicator that it's part of a sequence + const formattedText = messageCount > 0 ? `↪️ ${text}` : text + messageCount++ + const response = await fetch(webhookUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ text }) + body: JSON.stringify({ text: formattedText }) }) if (!response.ok) { diff --git a/src/test/slack.test.ts b/src/test/slack.test.ts index 990cf50acb..593a739b74 100644 --- a/src/test/slack.test.ts +++ b/src/test/slack.test.ts @@ -1,19 +1,70 @@ -import { setSlackEnabled, setWebhookUrl, sendSlackMessage, notifyTaskComplete, notifyUserInputNeeded, notifyTaskFailed, notifyCommandExecution } from '../services/slack' +import { setSlackEnabled, setWebhookUrl, sendSlackMessage, notifyTaskComplete, notifyUserInputNeeded, notifyTaskFailed, notifyCommandExecution, resetThread } from '../services/slack' describe('Slack Notifications', () => { let mockFetch: jest.Mock beforeEach(() => { - mockFetch = jest.fn() + mockFetch = jest.fn().mockImplementation(() => + Promise.resolve({ + ok: true, + text: () => Promise.resolve('ok') + }) + ) global.fetch = mockFetch setWebhookUrl('https://hooks.slack.com/services/test') setSlackEnabled(true) + resetThread() }) afterEach(() => { jest.resetAllMocks() setSlackEnabled(false) setWebhookUrl('') + resetThread() + }) + + it('should send first message without indicator', async () => { + await sendSlackMessage('First message') + expect(mockFetch).toHaveBeenCalledWith( + 'https://hooks.slack.com/services/test', + expect.objectContaining({ + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ text: 'First message' }) + }) + ) + }) + + it('should send subsequent messages with reply indicator', async () => { + // First message + await sendSlackMessage('First message') + + // Second message should have indicator + await sendSlackMessage('Second message') + expect(mockFetch).toHaveBeenLastCalledWith( + 'https://hooks.slack.com/services/test', + expect.objectContaining({ + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ text: '↪️ Second message' }) + }) + ) + }) + + it('should reset message sequence when slack is disabled', async () => { + await sendSlackMessage('First message') + await sendSlackMessage('Second message') + setSlackEnabled(false) + setSlackEnabled(true) + await sendSlackMessage('New message') + expect(mockFetch).toHaveBeenLastCalledWith( + 'https://hooks.slack.com/services/test', + expect.objectContaining({ + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ text: 'New message' }) + }) + ) }) it('should send task completion notification', async () => { @@ -88,4 +139,19 @@ describe('Slack Notifications', () => { }) ) }) + + it('should start new sequence after resetThread is called', async () => { + await sendSlackMessage('First message') + await sendSlackMessage('Second message') + resetThread() + await sendSlackMessage('New first message') + expect(mockFetch).toHaveBeenLastCalledWith( + 'https://hooks.slack.com/services/test', + expect.objectContaining({ + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ text: 'New first message' }) + }) + ) + }) }) \ No newline at end of file