From 3ffd525a4fd7fd021b0ca2a62a33cf5219b727da Mon Sep 17 00:00:00 2001 From: Nemo Godebski-Pedersen Date: Fri, 28 Feb 2025 16:32:00 +0000 Subject: [PATCH] testing for end of stream events --- src/components/ChatWidget.vue | 4 +++ src/obp/opey-functions.ts | 9 ++++++ src/test/ChatWidget.test.ts | 4 +-- src/test/opey-functions.test.ts | 57 +++++++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 2 deletions(-) diff --git a/src/components/ChatWidget.vue b/src/components/ChatWidget.vue index f8efcaf..4209f0d 100644 --- a/src/components/ChatWidget.vue +++ b/src/components/ChatWidget.vue @@ -224,6 +224,10 @@ export default { color: #fff; } +.user-input-container:hover { + border: 1px solid #979797; +} + .user-input-container:focus-within { border: 1px solid #fff; } diff --git a/src/obp/opey-functions.ts b/src/obp/opey-functions.ts index 230a7e2..930d11d 100644 --- a/src/obp/opey-functions.ts +++ b/src/obp/opey-functions.ts @@ -53,6 +53,15 @@ export async function processOpeyStream( } catch (e) { throw new Error(`Error parsing JSON: ${e}`); } + } else if (line === 'data: [DONE]') { + // Add the current assistant message to the messages list + context.messages.push(context.currentAssistantMessage); + // Reset the current assistant message + context.currentAssistantMessage = { + id: '', + role: 'assistant', + content: '', + }; } } } diff --git a/src/test/ChatWidget.test.ts b/src/test/ChatWidget.test.ts index 52f5f47..b65d04c 100644 --- a/src/test/ChatWidget.test.ts +++ b/src/test/ChatWidget.test.ts @@ -63,8 +63,8 @@ describe('ChatWidget', () => { await wrapper.vm.$nextTick() // Get the input element and trigger the keypress enter event - // This will probably fail if the class name of the input element changes - const input = wrapper.get('.user-input-container input') + // This will probably fail if the class name of the parent div is changed, or if the input type is moved i.e. from textarea to input or el-input + const input = wrapper.get('.user-input-container textarea') input.trigger('keypress.enter') expect(global.fetch).toHaveBeenCalled() }) diff --git a/src/test/opey-functions.test.ts b/src/test/opey-functions.test.ts index e69edaa..05756c4 100644 --- a/src/test/opey-functions.test.ts +++ b/src/test/opey-functions.test.ts @@ -95,6 +95,63 @@ describe('processOpeyStream', async () => { await OpeyModule.processOpeyStream(stream, mockContext) expect(mockContext.status).toBe('ready') }) + + it("should clear the placeholder assistant message, and update last assistant message when recieving the [DONE] signal", async () => { + // Mock a ReadableStream + const mockAsisstantMessage = "Hi I'm Opey, your personal banking assistant. I'll certainly not take over the world, no, not at all!" + // Split the message into chunks, but reappend the whitespace (this is to simulate llm tokens) + const mockMessageChunks = mockAsisstantMessage.split(" ") + for (let i = 0; i < mockMessageChunks.length; i++) { + // Don't add whitespace to the last chunk + if (i === mockMessageChunks.length - 1 ) { + mockMessageChunks[i] = `${mockMessageChunks[i]}` + break + } + mockMessageChunks[i] = `${mockMessageChunks[i]} ` + } + + // Fake the token stream + const stream = new ReadableStream({ + start(controller) { + for (let i = 0; i < mockMessageChunks.length; i++) { + controller.enqueue(new TextEncoder().encode(`data: {"type":"token","content":"${mockMessageChunks[i]}"}\n`)); + } + controller.enqueue(new TextEncoder().encode(`data: [DONE]\n`)); + controller.close(); + }, + }); + + // Replace current assistant message with a more unique one for our test + mockContext.currentAssistantMessage = { + id: '456', + role: 'assistant', + content: '', + } + + // Push assistant message to the messages list as this is what we do in the ChatWidget to visualise token streaming + mockContext.messages.push(mockContext.currentAssistantMessage) + + await OpeyModule.processOpeyStream(stream, mockContext) + // assert that the current assistant 'placeholder' message was reset + expect(mockContext.currentAssistantMessage.content).toBe('') + // assert that the assistant message was added to the messages list + console.log(mockContext.messages) + expect(mockContext.messages).toContainEqual({ + id: '456', + role: 'assistant', + content: mockAsisstantMessage, + }) + + + }) + it("should not have a unique set of messages", async () => { + // mock the stream as above + function hasUniqueValues(arr: OpeyModule.OpeyMessage[]): boolean { + return arr.filter((value, index, self) => self.indexOf(value) === index).length === arr.length; + } + expect(hasUniqueValues(mockContext.messages)).toBe(true) + }) + }) describe('sendOpeyMessage', () => {