Skip to content

Commit 158be50

Browse files
authored
Fix chat history (#346)
1 parent d141aa5 commit 158be50

File tree

5 files changed

+106
-42
lines changed

5 files changed

+106
-42
lines changed

conversations/conversations.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@ const AnalysisTypeProp = "prompt_type"
3030

3131
// AIThread represents a user's conversation with an AI
3232
type AIThread struct {
33-
ID string `json:"id"`
34-
Title string `json:"title"`
35-
ChannelID string `json:"channel_id"`
36-
BotID string `json:"bot_id"`
37-
UpdatedAt int64 `json:"updated_at"`
33+
ID string `json:"id"`
34+
Message string `json:"message"`
35+
Title string `json:"title"`
36+
ChannelID string `json:"channel_id"`
37+
ReplyCount int `json:"reply_count"`
38+
UpdateAt int64 `json:"update_at"`
3839
}
3940

4041
type Conversations struct {

conversations/store.go

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,8 @@ func (c *Conversations) SaveTitle(threadID, title string) error {
3030
return err
3131
}
3232

33-
// This is a different AIThread struct than the one in conversations.go, used for database queries
34-
type aiThreadData struct {
35-
ID string
36-
Message string
37-
ChannelID string
38-
Title string
39-
ReplyCount int
40-
UpdateAt int64
41-
}
42-
4333
func (c *Conversations) getAIThreads(dmChannelIDs []string) ([]AIThread, error) {
44-
var dbPosts []aiThreadData
34+
var dbPosts []AIThread
4535
if err := c.db.DoQuery(&dbPosts, c.db.Builder().
4636
Select(
4737
"p.Id",
@@ -63,17 +53,5 @@ func (c *Conversations) getAIThreads(dmChannelIDs []string) ([]AIThread, error)
6353
return nil, fmt.Errorf("failed to get posts for bot DM: %w", err)
6454
}
6555

66-
// Convert from internal type to public AIThread type
67-
result := make([]AIThread, len(dbPosts))
68-
for i, post := range dbPosts {
69-
result[i] = AIThread{
70-
ID: post.ID,
71-
Title: post.Title,
72-
ChannelID: post.ChannelID,
73-
BotID: "", // We don't have this info in the query
74-
UpdatedAt: post.UpdateAt,
75-
}
76-
}
77-
78-
return result, nil
56+
return dbPosts, nil
7957
}

e2e/helpers/ai-plugin.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ export class AIPlugin {
66
readonly rhsPostTextarea: Locator;
77
readonly rhsSendButton: Locator;
88
readonly regenerateButton: Locator;
9+
readonly chatHistoryButton: Locator;
10+
readonly threadsListContainer: Locator;
911
readonly promptTemplates: {
1012
[key: string]: Locator;
1113
};
@@ -16,6 +18,8 @@ export class AIPlugin {
1618
this.rhsPostTextarea = page.getByTestId('rhs-new-tab-create-post').locator('textarea');
1719
this.rhsSendButton = page.locator('#rhsContainer').getByTestId('SendMessageButton');
1820
this.regenerateButton = page.getByRole('button', { name: 'Regenerate' });
21+
this.chatHistoryButton = page.getByTestId('chat-history');
22+
this.threadsListContainer = page.getByTestId('rhs-threads-list');
1923
this.promptTemplates = {
2024
'brainstorm': page.getByRole('button', { name: 'Brainstorm ideas' }),
2125
'todo': page.getByRole('button', { name: 'To-do list' }),
@@ -54,4 +58,19 @@ export class AIPlugin {
5458
async expectTextInTextarea(text: string) {
5559
await expect(this.rhsPostTextarea).toHaveText(text);
5660
}
61+
62+
async openChatHistory() {
63+
await this.chatHistoryButton.click();
64+
await expect(this.threadsListContainer).toBeVisible();
65+
}
66+
67+
async expectChatHistoryVisible() {
68+
await expect(this.threadsListContainer).toBeVisible();
69+
}
70+
71+
async clickChatHistoryItem(index: number = 0) {
72+
const threadItems = this.threadsListContainer.locator('div').first();
73+
await threadItems.nth(index).click();
74+
}
75+
5776
}

e2e/tests/basic.spec.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,69 @@ test.describe('Error Handling', () => {
131131
await expect(page.getByText(/An error occurred/i)).toBeVisible();
132132
});
133133
});
134+
135+
test.describe('Chat History', () => {
136+
test('can view chat history after creating conversations', async ({ page }) => {
137+
const { aiPlugin } = await setupTestPage(page);
138+
await aiPlugin.openRHS();
139+
140+
// Create first conversation
141+
await openAIMock.addCompletionMock(responseTest);
142+
await aiPlugin.sendMessage('First conversation message');
143+
await aiPlugin.waitForBotResponse(responseTestText);
144+
145+
// Create second conversation by starting new chat
146+
await page.getByTestId('new-chat').click();
147+
await openAIMock.addCompletionMock(responseTest2);
148+
await aiPlugin.sendMessage('Second conversation message');
149+
await aiPlugin.waitForBotResponse(responseTest2Text);
150+
151+
// Open chat history
152+
await aiPlugin.openChatHistory();
153+
await aiPlugin.expectChatHistoryVisible();
154+
155+
// Verify we can see conversation entries
156+
await expect(aiPlugin.threadsListContainer.locator('div').first()).toBeVisible();
157+
});
158+
159+
test('can click on chat history items without errors', async ({ page }) => {
160+
const { aiPlugin } = await setupTestPage(page);
161+
await aiPlugin.openRHS();
162+
163+
// Create a conversation first
164+
await openAIMock.addCompletionMock(responseTest);
165+
await aiPlugin.sendMessage('Test conversation');
166+
await aiPlugin.waitForBotResponse(responseTestText);
167+
168+
// Open chat history
169+
await aiPlugin.openChatHistory();
170+
await aiPlugin.expectChatHistoryVisible();
171+
172+
// Click on the first history item
173+
await aiPlugin.clickChatHistoryItem(0);
174+
175+
// Verify we can see the conversation content we created
176+
await expect(page.getByText('Test conversation')).toBeVisible();
177+
await expect(page.getByText(responseTestText)).toBeVisible();
178+
});
179+
180+
test('chat history button is visible and functional', async ({ page }) => {
181+
const { aiPlugin } = await setupTestPage(page);
182+
await aiPlugin.openRHS();
183+
184+
// Create a conversation first so we have content in the history
185+
await openAIMock.addCompletionMock(responseTest);
186+
await aiPlugin.sendMessage('Test for history button');
187+
await aiPlugin.waitForBotResponse(responseTestText);
188+
189+
// Chat history button should be visible
190+
await expect(aiPlugin.chatHistoryButton).toBeVisible();
191+
192+
// Should be clickable
193+
await aiPlugin.chatHistoryButton.click();
194+
195+
// Should show threads list with content
196+
await expect(aiPlugin.threadsListContainer).toBeVisible();
197+
await expect(aiPlugin.threadsListContainer.locator('div').first()).toBeVisible();
198+
});
199+
});

webapp/src/components/rhs/rhs.tsx

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,12 @@ const RHSBullet = styled.li`
5252
`;
5353

5454
export interface AIThread {
55-
ID: string;
56-
Message: string;
57-
ChannelID: string;
58-
Title: string;
59-
ReplyCount: number;
60-
UpdateAt: number;
55+
id: string;
56+
message: string;
57+
channel_id: string;
58+
title: string;
59+
reply_count: number;
60+
update_at: number;
6161
}
6262

6363
const twentyFourHoursInMS = 24 * 60 * 60 * 1000;
@@ -142,15 +142,15 @@ export default function RHS() {
142142
>
143143
{threads.map((p) => (
144144
<ThreadItem
145-
key={p.ID}
146-
postTitle={p.Title}
147-
postMessage={p.Message}
148-
repliesCount={p.ReplyCount}
149-
lastActivityDate={p.UpdateAt}
150-
label={bots.find((bot) => bot.dmChannelID === p.ChannelID)?.displayName ?? ''}
145+
key={p.id}
146+
postTitle={p.title}
147+
postMessage={p.message}
148+
repliesCount={p.reply_count}
149+
lastActivityDate={p.update_at}
150+
label={bots.find((bot) => bot.dmChannelID === p.channel_id)?.displayName ?? ''}
151151
onClick={() => {
152152
setCurrentTab('thread');
153-
selectPost(p.ID);
153+
selectPost(p.id);
154154
}}
155155
/>))}
156156
</ThreadsList>

0 commit comments

Comments
 (0)