@@ -206,6 +206,56 @@ def test_parse_response_model_sanitizes_operation_name_in_errors():
206206 )
207207
208208
209+ def test_parse_response_model_wraps_operation_name_strip_failures ():
210+ class _BrokenOperationName (str ):
211+ def strip (self , chars = None ): # type: ignore[override]
212+ _ = chars
213+ raise RuntimeError ("operation name strip exploded" )
214+
215+ with pytest .raises (HyperbrowserError , match = "Failed to normalize operation_name" ) as exc_info :
216+ parse_response_model (
217+ {"success" : True },
218+ model = BasicResponse ,
219+ operation_name = _BrokenOperationName ("basic operation" ),
220+ )
221+
222+ assert isinstance (exc_info .value .original_error , RuntimeError )
223+
224+
225+ def test_parse_response_model_preserves_hyperbrowser_operation_name_strip_failures ():
226+ class _BrokenOperationName (str ):
227+ def strip (self , chars = None ): # type: ignore[override]
228+ _ = chars
229+ raise HyperbrowserError ("custom operation name strip failure" )
230+
231+ with pytest .raises (
232+ HyperbrowserError , match = "custom operation name strip failure"
233+ ) as exc_info :
234+ parse_response_model (
235+ {"success" : True },
236+ model = BasicResponse ,
237+ operation_name = _BrokenOperationName ("basic operation" ),
238+ )
239+
240+ assert exc_info .value .original_error is None
241+
242+
243+ def test_parse_response_model_wraps_non_string_operation_name_strip_results ():
244+ class _BrokenOperationName (str ):
245+ def strip (self , chars = None ): # type: ignore[override]
246+ _ = chars
247+ return object ()
248+
249+ with pytest .raises (HyperbrowserError , match = "Failed to normalize operation_name" ) as exc_info :
250+ parse_response_model (
251+ {"success" : True },
252+ model = BasicResponse ,
253+ operation_name = _BrokenOperationName ("basic operation" ),
254+ )
255+
256+ assert isinstance (exc_info .value .original_error , TypeError )
257+
258+
209259def test_parse_response_model_truncates_operation_name_in_errors ():
210260 long_operation_name = "basic operation " + ("x" * 200 )
211261
@@ -223,6 +273,35 @@ def test_parse_response_model_truncates_operation_name_in_errors():
223273 )
224274
225275
276+ def test_parse_response_model_falls_back_for_unreadable_key_display ():
277+ class _BrokenKey (str ):
278+ def __iter__ (self ):
279+ raise RuntimeError ("key iteration exploded" )
280+
281+ class _BrokenValueLookupMapping (Mapping [str , object ]):
282+ def __iter__ (self ):
283+ yield _BrokenKey ("success" )
284+
285+ def __len__ (self ) -> int :
286+ return 1
287+
288+ def __getitem__ (self , key : str ) -> object :
289+ _ = key
290+ raise RuntimeError ("cannot read value" )
291+
292+ with pytest .raises (
293+ HyperbrowserError ,
294+ match = "Failed to read basic operation response value for key '<unreadable key>'" ,
295+ ) as exc_info :
296+ parse_response_model (
297+ _BrokenValueLookupMapping (),
298+ model = BasicResponse ,
299+ operation_name = "basic operation" ,
300+ )
301+
302+ assert isinstance (exc_info .value .original_error , RuntimeError )
303+
304+
226305def test_parse_response_model_wraps_mapping_read_failures ():
227306 with pytest .raises (
228307 HyperbrowserError ,
0 commit comments