9
9
from tenantfirstaid .chat import ChatView
10
10
from tenantfirstaid .session import TenantSession , TenantSessionData , InitSessionView
11
11
from vertexai .generative_models import (
12
- GenerationConfig ,
13
- GenerationResponse ,
14
12
GenerativeModel ,
13
+ Tool ,
15
14
)
16
15
from typing import Dict
17
16
@@ -89,8 +88,21 @@ def app(mock_valkey):
89
88
90
89
91
90
def test_chat_view_dispatch_request_streams_response (
92
- app , mocker , mock_vertexai_generative_model
91
+ app , mocker , mock_vertexai_generative_model , mock_valkey
93
92
):
93
+ """Test that sends a message to the API, mocks vertexai response, and validates output."""
94
+
95
+ # Mock the entire RAG module components to avoid actual RAG retrieval
96
+ mock_rag_resource = mocker .Mock ()
97
+ mock_rag_store = mocker .Mock ()
98
+ mock_retrieval = mocker .Mock ()
99
+ mock_rag_tool = mocker .Mock (spec = Tool )
100
+
101
+ mocker .patch ("tenantfirstaid.chat.rag.RagResource" , return_value = mock_rag_resource )
102
+ mocker .patch ("tenantfirstaid.chat.rag.VertexRagStore" , return_value = mock_rag_store )
103
+ mocker .patch ("tenantfirstaid.chat.rag.Retrieval" , return_value = mock_retrieval )
104
+ mocker .patch ("tenantfirstaid.chat.Tool.from_retrieval" , return_value = mock_rag_tool )
105
+
94
106
tenant_session = TenantSession ()
95
107
96
108
app .add_url_rule (
@@ -106,57 +118,70 @@ def test_chat_view_dispatch_request_streams_response(
106
118
)
107
119
108
120
test_data_obj = TenantSessionData (
109
- city = "Test City " ,
110
- state = "Test State " ,
121
+ city = "Portland " ,
122
+ state = "or " ,
111
123
messages = [],
112
124
)
113
125
114
- # Initialize the session with session_id and test data
115
- with app .test_request_context (
116
- "/api/init" , method = "POST" , json = test_data_obj
117
- ) as init_ctx :
126
+ # Initialize the session
127
+ with app .test_request_context ("/api/init" , method = "POST" , json = test_data_obj ):
118
128
init_response = app .full_dispatch_request ()
119
- assert init_response .status_code == 200 # Ensure the response is successful
120
-
121
- tenant_session .set (test_data_obj )
129
+ assert init_response .status_code == 200
122
130
session_id = init_response .json ["session_id" ]
123
- assert session_id is not None # Ensure session_id is set
124
- assert isinstance (session_id , str ) # Ensure session_id is a string
125
- assert tenant_session .get () == test_data_obj
126
131
127
- # each test-request is a new context (nesting does not do what you think)
128
- # so we need to set the session_id in the request context manually
132
+ # Mock the GenerativeModel's generate_content method
133
+ mock_response_text = "This is a mocked response about tenant rights in Oregon. You should contact <a href='https://oregon.public.law/statutes/ORS_90.427' target='_blank'>ORS 90.427</a> for more information."
134
+
135
+ # Create a mock response object that mimics the streaming response
136
+ mock_candidate = mocker .Mock ()
137
+ mock_candidate .content .parts = [mocker .Mock ()]
138
+ mock_candidate .content .parts [0 ].text = mock_response_text
139
+
140
+ mock_event = mocker .Mock ()
141
+ mock_event .candidates = [mock_candidate ]
142
+
143
+ # Mock the generate_content method to return our mock response as a stream
144
+ mock_vertexai_generative_model .generate_content .return_value = iter ([mock_event ])
145
+
146
+ # Send a message to the chat API
147
+ test_message = "What are my rights as a tenant in Portland?"
148
+
129
149
with app .test_request_context (
130
- "/api/query" , method = "POST" , json = {"message" : "Salutations mock openai api" }
150
+ "/api/query" , method = "POST" , json = {"message" : test_message }
131
151
) as chat_ctx :
132
- with mocker .patch ("tenantfirstaid.chat.GenerativeModel" ) as mock_model :
133
- chat_ctx .session ["session_id" ] = (
134
- session_id # Simulate session ID in request context
135
- )
136
- chat_response = init_ctx .app .full_dispatch_request ()
137
- assert chat_response .status_code == 200 # Ensure the response is successful
138
- assert chat_response .mimetype == "text/plain"
139
-
140
- mock_model .generate_content = mocker .Mock (
141
- return_value = iter (
142
- [
143
- GenerationResponse .from_dict (
144
- response_dict = dict (
145
- candidates = [
146
- dict (
147
- content = dict (
148
- role = "model" ,
149
- parts = [
150
- dict (text = "Greetings, test prompt!" )
151
- ],
152
- )
153
- )
154
- ]
155
- )
156
- )
157
- ]
158
- )
159
- )
160
-
161
- response_chunks = "" .join (chat_response .response )
162
- assert "Greetings, test prompt!" in response_chunks
152
+ chat_ctx .session ["session_id" ] = session_id
153
+
154
+ # Execute the request
155
+ chat_response = chat_ctx .app .full_dispatch_request ()
156
+
157
+ # Verify the response
158
+ assert chat_response .status_code == 200
159
+ assert chat_response .mimetype == "text/plain"
160
+
161
+ # Get the response data by consuming the stream
162
+ response_data = "" .join (
163
+ chunk .decode ("utf-8" ) if isinstance (chunk , bytes ) else chunk
164
+ for chunk in chat_response .response
165
+ )
166
+ assert response_data == mock_response_text
167
+
168
+ # Verify that generate_content was called with correct parameters
169
+ mock_vertexai_generative_model .generate_content .assert_called_once ()
170
+ call_args = mock_vertexai_generative_model .generate_content .call_args
171
+
172
+ # Check that the user message was included in the call
173
+ contents = call_args [1 ]["contents" ] # keyword arguments
174
+ assert len (contents ) == 1
175
+ assert contents [0 ]["role" ] == "user"
176
+ assert contents [0 ]["parts" ][0 ]["text" ] == test_message
177
+
178
+ # Check that streaming was enabled
179
+ assert call_args [1 ]["stream" ] is True
180
+
181
+ # Verify the session was updated with both user and assistant messages
182
+ updated_session = tenant_session .get ()
183
+ assert len (updated_session ["messages" ]) == 2
184
+ assert updated_session ["messages" ][0 ]["role" ] == "user"
185
+ assert updated_session ["messages" ][0 ]["content" ] == test_message
186
+ assert updated_session ["messages" ][1 ]["role" ] == "model"
187
+ assert updated_session ["messages" ][1 ]["content" ] == mock_response_text
0 commit comments