1616class TestFeedbackToolValidation :
1717 """Test suite for feedback tool input validation."""
1818
19- def test_validation_errors (self ) -> None :
20- """Test all validation error cases in one comprehensive test ."""
19+ def test_missing_required_fields (self ) -> None :
20+ """Test validation errors for missing required fields ."""
2121 tool = create_feedback_tool (api_key = "test_key" )
2222
23- # Test missing required fields
2423 with pytest .raises (StackOneError , match = "account_id" ):
2524 tool .execute ({"feedback" : "Great tools!" , "tool_names" : ["test_tool" ]})
2625
@@ -30,7 +29,10 @@ def test_validation_errors(self) -> None:
3029 with pytest .raises (StackOneError , match = "feedback" ):
3130 tool .execute ({"account_id" : "acc_123456" , "tool_names" : ["test_tool" ]})
3231
33- # Test empty/whitespace strings
32+ def test_empty_and_whitespace_validation (self ) -> None :
33+ """Test validation for empty and whitespace-only strings."""
34+ tool = create_feedback_tool (api_key = "test_key" )
35+
3436 with pytest .raises (StackOneError , match = "non-empty" ):
3537 tool .execute ({"feedback" : " " , "account_id" : "acc_123456" , "tool_names" : ["test_tool" ]})
3638
@@ -43,64 +45,43 @@ def test_validation_errors(self) -> None:
4345 with pytest .raises (StackOneError , match = "At least one tool name" ):
4446 tool .execute ({"feedback" : "Great!" , "account_id" : "acc_123456" , "tool_names" : [" " , " " ]})
4547
46- # Test JSON string input
47- with patch ("requests.request" ) as mock_request :
48- mock_response = Mock ()
49- mock_response .status_code = 200
50- mock_response .json .return_value = {"message" : "Success" }
51- mock_response .raise_for_status = Mock ()
52- mock_request .return_value = mock_response
53-
54- json_string = json .dumps (
55- {"feedback" : "Great tools!" , "account_id" : "acc_123456" , "tool_names" : ["test_tool" ]}
56- )
57- result = tool .execute (json_string )
58- assert result ["message" ] == "Success"
59-
6048 def test_multiple_account_ids_validation (self ) -> None :
6149 """Test validation with multiple account IDs."""
6250 tool = create_feedback_tool (api_key = "test_key" )
6351
64- # Test empty account ID list
6552 with pytest .raises (StackOneError , match = "At least one account ID is required" ):
6653 tool .execute ({"feedback" : "Great tools!" , "account_id" : [], "tool_names" : ["test_tool" ]})
6754
68- # Test account ID list with empty strings
6955 with pytest .raises (StackOneError , match = "At least one valid account ID is required" ):
7056 tool .execute ({"feedback" : "Great tools!" , "account_id" : ["" , " " ], "tool_names" : ["test_tool" ]})
7157
72- # Test valid multiple account IDs
58+ def test_json_string_input (self ) -> None :
59+ """Test that JSON string input is properly parsed."""
60+ tool = create_feedback_tool (api_key = "test_key" )
61+
7362 with patch ("requests.request" ) as mock_request :
7463 mock_response = Mock ()
7564 mock_response .status_code = 200
7665 mock_response .json .return_value = {"message" : "Success" }
7766 mock_response .raise_for_status = Mock ()
7867 mock_request .return_value = mock_response
7968
80- result = tool .execute (
81- {
82- "feedback" : "Great tools!" ,
83- "account_id" : ["acc_123456" , "acc_789012" ],
84- "tool_names" : ["test_tool" ],
85- }
86- )
87- assert "total_accounts" in result
88- assert result ["total_accounts" ] == 2
69+ json_string = json .dumps ({
70+ "feedback" : "Great tools!" ,
71+ "account_id" : "acc_123456" ,
72+ "tool_names" : ["test_tool" ]
73+ })
74+ result = tool .execute (json_string )
75+ assert result ["message" ] == "Success"
8976
9077
9178class TestFeedbackToolExecution :
9279 """Test suite for feedback tool execution."""
9380
94- def test_submits_feedback_to_api (self ) -> None :
95- """Test that feedback is submitted to the API with proper structure ."""
81+ def test_single_account_execution (self ) -> None :
82+ """Test execution with single account ID ."""
9683 tool = create_feedback_tool (api_key = "test_key" )
97-
98- api_response = {
99- "message" : "Feedback successfully stored" ,
100- "key" : "2025-10-08T11-44-16.123Z-a3f7b2c1d4e5f6a7b8c9d0e1f2a3b4c5.json" ,
101- "submitted_at" : "2025-10-08T11:44:16.123Z" ,
102- "trace_id" : "30d37876-cb1a-4138-9225-197355e0b6c9" ,
103- }
84+ api_response = {"message" : "Feedback successfully stored" , "trace_id" : "test-trace-id" }
10485
10586 with patch ("requests.request" ) as mock_request :
10687 mock_response = Mock ()
@@ -109,18 +90,13 @@ def test_submits_feedback_to_api(self) -> None:
10990 mock_response .raise_for_status = Mock ()
11091 mock_request .return_value = mock_response
11192
112- result = tool .execute (
113- {
114- "feedback" : "Great tools!" ,
115- "account_id" : "acc_123456" ,
116- "tool_names" : ["data_export" , "analytics" ],
117- }
118- )
119-
120- assert result ["message" ] == "Feedback successfully stored"
121- assert result ["trace_id" ] == "30d37876-cb1a-4138-9225-197355e0b6c9"
93+ result = tool .execute ({
94+ "feedback" : "Great tools!" ,
95+ "account_id" : "acc_123456" ,
96+ "tool_names" : ["data_export" , "analytics" ],
97+ })
12298
123- # Verify the API was called correctly
99+ assert result == api_response
124100 mock_request .assert_called_once ()
125101 call_kwargs = mock_request .call_args [1 ]
126102 assert call_kwargs ["method" ] == "POST"
@@ -129,16 +105,10 @@ def test_submits_feedback_to_api(self) -> None:
129105 assert call_kwargs ["json" ]["account_id" ] == "acc_123456"
130106 assert call_kwargs ["json" ]["tool_names" ] == ["data_export" , "analytics" ]
131107
132- def test_call_method_works (self ) -> None :
108+ def test_call_method_interface (self ) -> None :
133109 """Test that the .call() method works correctly."""
134110 tool = create_feedback_tool (api_key = "test_key" )
135-
136- api_response = {
137- "message" : "Feedback successfully stored" ,
138- "key" : "test-key.json" ,
139- "submitted_at" : "2025-10-08T11:44:16.123Z" ,
140- "trace_id" : "test-trace-id" ,
141- }
111+ api_response = {"message" : "Success" , "trace_id" : "test-trace-id" }
142112
143113 with patch ("requests.request" ) as mock_request :
144114 mock_response = Mock ()
@@ -155,12 +125,8 @@ def test_call_method_works(self) -> None:
155125
156126 assert result == api_response
157127 mock_request .assert_called_once ()
158- call_kwargs = mock_request .call_args [1 ]
159- assert call_kwargs ["json" ]["feedback" ] == "Testing the .call() method interface."
160- assert call_kwargs ["json" ]["account_id" ] == "acc_test004"
161- assert call_kwargs ["json" ]["tool_names" ] == ["meta_collect_tool_feedback" ]
162128
163- def test_handles_api_errors (self ) -> None :
129+ def test_api_error_handling (self ) -> None :
164130 """Test that API errors are handled properly."""
165131 tool = create_feedback_tool (api_key = "test_key" )
166132
@@ -173,73 +139,48 @@ def test_handles_api_errors(self) -> None:
173139 mock_request .return_value = mock_response
174140
175141 with pytest .raises (StackOneError ):
176- tool .execute (
177- {
178- "feedback" : "Great tools!" ,
179- "account_id" : "acc_123456" ,
180- "tool_names" : ["test_tool" ],
181- }
182- )
142+ tool .execute ({
143+ "feedback" : "Great tools!" ,
144+ "account_id" : "acc_123456" ,
145+ "tool_names" : ["test_tool" ],
146+ })
183147
184148 def test_multiple_account_ids_execution (self ) -> None :
185- """Test execution with multiple account IDs."""
149+ """Test execution with multiple account IDs - both success and mixed scenarios ."""
186150 tool = create_feedback_tool (api_key = "test_key" )
151+ api_response = {"message" : "Feedback successfully stored" , "trace_id" : "test-trace-id" }
187152
188- api_response = {
189- "message" : "Feedback successfully stored" ,
190- "key" : "test-key.json" ,
191- "submitted_at" : "2025-10-08T11:44:16.123Z" ,
192- "trace_id" : "test-trace-id" ,
193- }
194-
153+ # Test all successful case
195154 with patch ("requests.request" ) as mock_request :
196155 mock_response = Mock ()
197156 mock_response .status_code = 200
198157 mock_response .json .return_value = api_response
199158 mock_response .raise_for_status = Mock ()
200159 mock_request .return_value = mock_response
201160
202- result = tool .execute (
203- {
204- "feedback" : "Great tools!" ,
205- "account_id" : ["acc_123456" , "acc_789012" , "acc_345678" ],
206- "tool_names" : ["test_tool" ],
207- }
208- )
161+ result = tool .execute ({
162+ "feedback" : "Great tools!" ,
163+ "account_id" : ["acc_123456" , "acc_789012" , "acc_345678" ],
164+ "tool_names" : ["test_tool" ],
165+ })
209166
210- # Check combined result structure
211167 assert result ["message" ] == "Feedback sent to 3 account(s)"
212168 assert result ["total_accounts" ] == 3
213169 assert result ["successful" ] == 3
214170 assert result ["failed" ] == 0
215171 assert len (result ["results" ]) == 3
216-
217- # Check individual results
218- for i , account_id in enumerate (["acc_123456" , "acc_789012" , "acc_345678" ]):
219- assert result ["results" ][i ]["account_id" ] == account_id
220- assert result ["results" ][i ]["status" ] == "success"
221- assert result ["results" ][i ]["result" ] == api_response
222-
223- # Verify API was called 3 times
224172 assert mock_request .call_count == 3
225173
226- def test_multiple_account_ids_with_errors (self ) -> None :
227- """Test execution with multiple account IDs where some fail."""
228- tool = create_feedback_tool (api_key = "test_key" )
229-
230- success_response = {"message" : "Success" }
231-
174+ # Test mixed success/error case
232175 def mock_request_side_effect (* args , ** kwargs ):
233176 account_id = kwargs .get ("json" , {}).get ("account_id" )
234177 if account_id == "acc_123456" :
235- # Success case
236178 mock_response = Mock ()
237179 mock_response .status_code = 200
238- mock_response .json .return_value = success_response
180+ mock_response .json .return_value = { "message" : "Success" }
239181 mock_response .raise_for_status = Mock ()
240182 return mock_response
241183 else :
242- # Error case
243184 mock_response = Mock ()
244185 mock_response .status_code = 401
245186 mock_response .text = '{"error": "Unauthorized"}'
@@ -250,35 +191,26 @@ def mock_request_side_effect(*args, **kwargs):
250191 with patch ("requests.request" ) as mock_request :
251192 mock_request .side_effect = mock_request_side_effect
252193
253- result = tool .execute (
254- {
255- "feedback" : "Great tools!" ,
256- "account_id" : ["acc_123456" , "acc_unauthorized" ],
257- "tool_names" : ["test_tool" ],
258- }
259- )
194+ result = tool .execute ({
195+ "feedback" : "Great tools!" ,
196+ "account_id" : ["acc_123456" , "acc_unauthorized" ],
197+ "tool_names" : ["test_tool" ],
198+ })
260199
261- # Check combined result structure
262200 assert result ["total_accounts" ] == 2
263201 assert result ["successful" ] == 1
264202 assert result ["failed" ] == 1
265203 assert len (result ["results" ]) == 2
266204
267- # Check individual results
268205 success_result = next (r for r in result ["results" ] if r ["account_id" ] == "acc_123456" )
269206 assert success_result ["status" ] == "success"
270- assert success_result ["result" ] == success_response
271207
272208 error_result = next (r for r in result ["results" ] if r ["account_id" ] == "acc_unauthorized" )
273209 assert error_result ["status" ] == "error"
274210 assert "401 Client Error: Unauthorized" in error_result ["error" ]
275211
276-
277- class TestFeedbackToolIntegration :
278- """Test suite for feedback tool integration."""
279-
280- def test_feedback_tool_integration (self ) -> None :
281- """Test that feedback tool integrates properly with toolset and has correct structure."""
212+ def test_tool_integration (self ) -> None :
213+ """Test that feedback tool integrates properly with toolset."""
282214 from stackone_ai import StackOneToolSet
283215
284216 with patch .dict ("os.environ" , {"STACKONE_API_KEY" : "test_key" }):
@@ -298,11 +230,6 @@ def test_feedback_tool_integration(self) -> None:
298230 assert "account_id" in openai_format ["function" ]["parameters" ]["properties" ]
299231 assert "tool_names" in openai_format ["function" ]["parameters" ]["properties" ]
300232
301- # Test LangChain format
302- langchain_tool = feedback_tool .to_langchain ()
303- assert langchain_tool .name == "meta_collect_tool_feedback"
304- assert "feedback" in langchain_tool .description .lower ()
305-
306233
307234@pytest .mark .integration
308235def test_live_feedback_submission () -> None :
0 commit comments