1
1
import React from 'react'
2
- import { fireEvent , render , screen } from '@testing-library/react'
3
- import '@testing-library/jest-dom'
4
- import ChatMessageContainer , { parseCitationFromMessage } from './ChatMessageContainer'
5
-
6
- import { type ChatMessage } from '../../api'
7
-
2
+ import { render , screen , fireEvent } from '@testing-library/react'
3
+ import { ChatMessageContainer } from './ChatMessageContainer'
4
+ import { type ChatMessage } from '../../api/models'
5
+ import { Answer } from '../Answer'
8
6
jest . mock ( 'remark-supersub' , ( ) => ( ) => { } )
9
7
jest . mock ( 'remark-gfm' , ( ) => ( ) => { } )
10
8
jest . mock ( 'rehype-raw' , ( ) => ( ) => { } )
11
- jest . mock ( '../Answer' , ( ) => ( {
9
+ jest . mock ( '../Answer/Answer ' , ( ) => ( {
12
10
Answer : jest . fn ( ( props : any ) => < div >
13
11
< p > { props . answer . answer } </ p >
14
12
< span > Mock Answer Component</ span >
15
- { props . answer . answer === 'Generating answer...'
13
+ { props . answer . answer == 'Generating answer...'
16
14
? < button onClick = { ( ) => props . onCitationClicked ( ) } > Mock Citation Loading</ button >
17
- : < button onClick = { ( ) => props . onCitationClicked ( { title : 'Test Citation' } ) } > Mock Citation</ button >
15
+ : < button aria-label = "citationButton" onClick = { ( ) => props . onCitationClicked ( { title : 'Test Citation' } ) } > Mock Citation</ button >
18
16
}
19
17
20
18
</ div > )
21
19
} ) )
22
20
23
21
const mockOnShowCitation = jest . fn ( )
22
+
24
23
describe ( 'ChatMessageContainer' , ( ) => {
25
24
beforeEach ( ( ) => {
26
25
global . fetch = jest . fn ( )
@@ -52,26 +51,36 @@ describe('ChatMessageContainer', () => {
52
51
date : new Date ( ) . toDateString ( )
53
52
}
54
53
55
- const nullMessage : ChatMessage = {
56
- role : '' ,
57
- content : 'Null role message' ,
58
- id : '4' ,
59
- date : ''
60
- }
61
- it ( 'renders user messages correctly' , ( ) => {
62
- render ( < ChatMessageContainer messages = { [ userMessage ] } onShowCitation = { mockOnShowCitation } showLoadingMessage = { false } /> )
63
- expect ( screen . getByText ( 'User message' ) ) . toBeInTheDocument ( )
64
- } )
54
+ it ( 'renders user and assistant messages correctly' , ( ) => {
55
+ render (
56
+ < ChatMessageContainer
57
+ messages = { [ userMessage , assistantMessage ] }
58
+ showLoadingMessage = { false }
59
+ onShowCitation = { mockOnShowCitation }
60
+ />
61
+ )
65
62
66
- it ( 'renders assistant messages correctly' , ( ) => {
67
- render ( < ChatMessageContainer messages = { [ assistantMessage ] } onShowCitation = { mockOnShowCitation } showLoadingMessage = { false } /> )
68
- expect ( screen . getByText ( 'Assistant message' ) ) . toBeInTheDocument ( )
63
+ // Check if user message is displayed
64
+ expect ( screen . getByText ( 'User message' ) ) . toBeInTheDocument ( )
65
+ screen . debug ( )
66
+ // Check if assistant message is displayed via Answer component
67
+ expect ( screen . getByText ( 'Mock Answer Component' ) ) . toBeInTheDocument ( )
68
+ expect ( Answer ) . toHaveBeenCalledWith (
69
+ expect . objectContaining ( {
70
+ answer : {
71
+ answer : 'Assistant message' ,
72
+ citations : [ ]
73
+ }
74
+ } ) ,
75
+ { }
76
+ )
69
77
} )
70
78
71
79
it ( 'renders an error message correctly' , ( ) => {
72
80
render (
73
81
< ChatMessageContainer
74
82
messages = { [ errorMessage ] }
83
+
75
84
showLoadingMessage = { false }
76
85
onShowCitation = { mockOnShowCitation }
77
86
/>
@@ -82,41 +91,64 @@ describe('ChatMessageContainer', () => {
82
91
expect ( screen . getByText ( 'Error message' ) ) . toBeInTheDocument ( )
83
92
} )
84
93
85
- it ( 'returns citations when message role is "tool" and content is valid JSON' , ( ) => {
86
- const message : ChatMessage = {
87
- role : 'tool' ,
88
- content : JSON . stringify ( { citations : [ { filepath : 'path/to/file' , chunk_id : '1' } ] } ) ,
89
- id : '1' ,
90
- date : ''
91
- }
92
- const citations = parseCitationFromMessage ( message )
93
- expect ( citations ) . toEqual ( [ { filepath : 'path/to/file' , chunk_id : '1' } ] )
94
+ it ( 'displays the loading message when showLoadingMessage is true' , ( ) => {
95
+ render (
96
+ < ChatMessageContainer
97
+ messages = { [ ] }
98
+
99
+ showLoadingMessage = { true }
100
+ onShowCitation = { mockOnShowCitation }
101
+ />
102
+ )
103
+ // Check if the loading message is displayed via Answer component
104
+ expect ( screen . getByText ( 'Generating answer...' ) ) . toBeInTheDocument ( )
105
+ } )
106
+
107
+ it ( 'calls onShowCitation when a citation is clicked' , ( ) => {
108
+ render (
109
+ < ChatMessageContainer
110
+ messages = { [ assistantMessage ] }
111
+ showLoadingMessage = { false }
112
+ onShowCitation = { mockOnShowCitation }
113
+ />
114
+ )
115
+
116
+ // Simulate a citation click
117
+ const citationButton = screen . getByText ( 'Mock Citation' )
118
+ fireEvent . click ( citationButton )
119
+
120
+ // Check if onShowCitation is called with the correct argument
121
+ expect ( mockOnShowCitation ) . toHaveBeenCalledWith ( { title : 'Test Citation' } )
94
122
} )
95
123
96
- it ( 'returns an empty array when message role is "tool" and content is invalid JSON' , ( ) => {
97
- const message : ChatMessage = {
98
- role : 'tool' ,
99
- content : 'invalid JSON' ,
100
- id : '1' ,
101
- date : ''
102
- }
103
- const citations = parseCitationFromMessage ( message )
104
- expect ( citations ) . toEqual ( [ ] )
124
+ test ( 'does not call onShowCitation when citation click is a no-op' , ( ) => {
125
+ render (
126
+ < ChatMessageContainer
127
+ messages = { [ ] }
128
+ showLoadingMessage = { true }
129
+ onShowCitation = { mockOnShowCitation } // No-op function
130
+ />
131
+ )
132
+ // Simulate a citation click
133
+ const citationButton = screen . getByRole ( 'button' , { name : 'Mock Citation Loading' } )
134
+ fireEvent . click ( citationButton )
135
+
136
+ // Check if onShowCitation is NOT called
137
+ expect ( mockOnShowCitation ) . not . toHaveBeenCalled ( )
105
138
} )
106
139
107
- it ( 'returns an empty array when message role is not "tool"' , ( ) => {
108
- const message : ChatMessage = {
109
- role : 'user' ,
110
- content : JSON . stringify ( { citations : [ { filepath : 'path/to/file' , chunk_id : '1' } ] } ) ,
111
- id : '1' ,
112
- date : ''
113
- }
114
- const citations = parseCitationFromMessage ( message )
115
- expect ( citations ) . toEqual ( [ ] )
140
+ test ( 'calls onShowCitation when citation button is clicked' , async ( ) => {
141
+ render ( < ChatMessageContainer messages = { [ userMessage , assistantMessage ] } onShowCitation = { mockOnShowCitation } showLoadingMessage = { false } /> )
142
+ const buttonEle = await screen . findByRole ( 'button' , { name : 'citationButton' } )
143
+ fireEvent . click ( buttonEle )
144
+ expect ( mockOnShowCitation ) . toHaveBeenCalledWith ( { title : 'Test Citation' } )
116
145
} )
117
146
118
- it ( 'handles null role messages correctly' , ( ) => {
119
- render ( < ChatMessageContainer messages = { [ nullMessage ] } onShowCitation = { mockOnShowCitation } showLoadingMessage = { false } /> )
120
- expect ( screen . queryByText ( 'Null role message' ) ) . not . toBeInTheDocument ( )
147
+ test ( 'does not call onCitationClicked when citation button is clicked' , async ( ) => {
148
+ const mockOnCitationClicked = jest . fn ( )
149
+ render ( < ChatMessageContainer messages = { [ userMessage , assistantMessage ] } onShowCitation = { mockOnShowCitation } showLoadingMessage = { false } /> )
150
+ const buttonEle = await screen . findByRole ( 'button' , { name : 'citationButton' } )
151
+ fireEvent . click ( buttonEle )
152
+ expect ( mockOnCitationClicked ) . not . toHaveBeenCalled ( )
121
153
} )
122
154
} )
0 commit comments