@@ -6,36 +6,79 @@ import { test, expect } from '@playwright/test';
66const uniqueMessage = `E2E hello ${ Date . now ( ) } ` ;
77
88test ( 'send a message on Triage and see live processing' , async ( { page } ) => {
9- let threadId : string | undefined ;
10- await page . goto ( '/triage' ) ;
11-
12- // New-conversation textarea (initial input)
13- const newConversationTextarea = page . getByPlaceholder ( 'Describe your Redis issue or ask a question...' ) ;
14- await newConversationTextarea . waitFor ( { state : 'visible' } ) ;
15-
16- // Type and send
17- await newConversationTextarea . fill ( uniqueMessage ) ;
18- await page . getByRole ( 'button' , { name : 'Send' } ) . click ( ) ;
19-
20- // Capture created thread id
21- const resp = await page . waitForResponse ( ( r ) => r . url ( ) . includes ( '/api/v1/tasks' ) && r . request ( ) . method ( ) === 'POST' ) ;
22- const data = await resp . json ( ) ;
23- threadId = data . thread_id as string ;
24-
25- try {
26- // After sending, UI enters a busy state and shows a Stop button while the task runs.
27- await expect ( page . getByRole ( 'button' , { name : 'Stop' } ) ) . toBeVisible ( { timeout : 30_000 } ) ;
28-
29- // The user's message should appear in the transcript area soon after sending.
30- // The message may appear both in the sidebar and in the chat bubble; assert the chat bubble copy.
31- await expect ( page . getByText ( uniqueMessage ) . last ( ) ) . toBeVisible ( { timeout : 30_000 } ) ;
32-
33- // Optional: stop the task to end the live run and return to transcript view.
34- await page . getByRole ( 'button' , { name : 'Stop' } ) . click ( ) ;
35- await expect ( page . getByRole ( 'button' , { name : 'Stop' } ) ) . toBeHidden ( { timeout : 30_000 } ) ;
36- } finally {
37- if ( threadId ) {
38- await page . request . delete ( `/api/v1/threads/${ threadId } ` ) ;
39- }
40- }
9+ let threadId : string | undefined ;
10+ await page . goto ( '/triage' ) ;
11+
12+ // New-conversation textarea (initial input)
13+ const newConversationTextarea = page . getByPlaceholder ( 'Describe your Redis issue or ask a question...' ) ;
14+ await newConversationTextarea . waitFor ( { state : 'visible' } ) ;
15+
16+ // Type and send
17+ await newConversationTextarea . fill ( uniqueMessage ) ;
18+ await page . getByRole ( 'button' , { name : 'Send' } ) . click ( ) ;
19+
20+ // Capture created thread id
21+ const resp = await page . waitForResponse ( ( r ) => r . url ( ) . includes ( '/api/v1/tasks' ) && r . request ( ) . method ( ) === 'POST' ) ;
22+ const data = await resp . json ( ) ;
23+ threadId = data . thread_id as string ;
24+
25+ try {
26+ // After sending, UI enters a busy state and shows a Stop button while the task runs.
27+ await expect ( page . getByRole ( 'button' , { name : 'Stop' } ) ) . toBeVisible ( { timeout : 30_000 } ) ;
28+
29+ // The user's message should appear in the transcript area soon after sending.
30+ // The message may appear both in the sidebar and in the chat bubble; assert the chat bubble copy.
31+ await expect ( page . getByText ( uniqueMessage ) . last ( ) ) . toBeVisible ( { timeout : 30_000 } ) ;
32+
33+ // Optional: stop the task to end the live run and return to transcript view.
34+ await page . getByRole ( 'button' , { name : 'Stop' } ) . click ( ) ;
35+ await expect ( page . getByRole ( 'button' , { name : 'Stop' } ) ) . toBeHidden ( { timeout : 30_000 } ) ;
36+ } finally {
37+ if ( threadId ) {
38+ await page . request . delete ( `/api/v1/threads/${ threadId } ` ) ;
39+ }
40+ }
41+ } ) ;
42+
43+ test ( 'New Chat from an existing thread shows the new conversation form' , async ( { page } ) => {
44+ let threadId : string | undefined ;
45+ await page . goto ( '/triage' ) ;
46+
47+ // Start a new conversation to create a thread
48+ const newConversationTextarea = page . getByPlaceholder ( 'Describe your Redis issue or ask a question...' ) ;
49+ await newConversationTextarea . waitFor ( { state : 'visible' } ) ;
50+ await newConversationTextarea . fill ( uniqueMessage ) ;
51+ await page . getByRole ( 'button' , { name : 'Send' } ) . click ( ) ;
52+
53+ // Capture created thread id
54+ const resp = await page . waitForResponse ( ( r ) => r . url ( ) . includes ( '/api/v1/tasks' ) && r . request ( ) . method ( ) === 'POST' ) ;
55+ const data = await resp . json ( ) ;
56+ threadId = data . thread_id as string ;
57+
58+ try {
59+ // Navigate to Triage with the thread query parameter as other pages do
60+ await page . goto ( `/triage?thread=${ threadId } ` ) ;
61+
62+ // Existing-thread composer should be visible
63+ const continueTextarea = page . getByPlaceholder ( 'Continue the conversation...' ) ;
64+ await expect ( continueTextarea ) . toBeVisible ( { timeout : 30_000 } ) ;
65+
66+ // Click New Chat in the Conversations sidebar
67+ await page . getByRole ( 'button' , { name : 'New Chat' } ) . click ( ) ;
68+
69+ // After New Chat, we should see the new-conversation form textarea
70+ const newChatTextarea = page . getByPlaceholder ( 'Describe your Redis issue or ask a question...' ) ;
71+ await expect ( newChatTextarea ) . toBeVisible ( { timeout : 30_000 } ) ;
72+
73+ // And the existing-thread composer should no longer be present
74+ await expect ( continueTextarea ) . toHaveCount ( 0 ) ;
75+
76+ // URL should no longer contain the thread query parameter
77+ const url = page . url ( ) ;
78+ expect ( url ) . not . toContain ( 'thread=' ) ;
79+ } finally {
80+ if ( threadId ) {
81+ await page . request . delete ( `/api/v1/threads/${ threadId } ` ) ;
82+ }
83+ }
4184} ) ;
0 commit comments