@@ -278,3 +278,76 @@ def test_case_insensitive_prefix_detection(self) -> None:
278278 hn = HumanName ("VINCENT VAN GOGH" )
279279 self .m (hn .last_prefixes , "VAN" , hn )
280280 self .m (hn .last_base , "GOGH" , hn )
281+
282+ # --- targets: leading non-first-name prefix becomes the surname ---
283+
284+ def test_leading_non_first_name_prefix_de (self ) -> None :
285+ hn = HumanName ("de Mesnil" )
286+ self .m (hn .first , "" , hn )
287+ self .m (hn .middle , "" , hn )
288+ self .m (hn .last , "de Mesnil" , hn )
289+
290+ def test_leading_non_first_name_prefix_dos (self ) -> None :
291+ hn = HumanName ("dos Santos" )
292+ self .m (hn .first , "" , hn )
293+ self .m (hn .last , "dos Santos" , hn )
294+
295+ def test_leading_non_first_name_prefix_chain (self ) -> None :
296+ hn = HumanName ("de la Vega" )
297+ self .m (hn .first , "" , hn )
298+ self .m (hn .last , "de la Vega" , hn )
299+
300+ def test_leading_non_first_name_prefix_derived_props (self ) -> None :
301+ hn = HumanName ("de Mesnil" )
302+ self .m (hn .last_prefixes , "de" , hn )
303+ self .m (hn .last_base , "Mesnil" , hn )
304+
305+ def test_non_first_name_prefix_with_custom_title (self ) -> None :
306+ # 'Gunny' is NOT a default title -> genuinely exercises the custom-title
307+ # path. Title is consumed first (first_list == ['']), so the fold does
308+ # not fire and the surname is already correct; asserts we don't corrupt
309+ # the title case.
310+ CONSTANTS .titles .add ('gunny' )
311+ hn = HumanName ("Gunny de Mesnil" )
312+ self .m (hn .title , "Gunny" , hn )
313+ self .m (hn .first , "" , hn )
314+ self .m (hn .last , "de Mesnil" , hn )
315+
316+ # --- safety: excluded / ambiguous particles are unchanged ---
317+
318+ def test_leading_von_is_unchanged (self ) -> None :
319+ hn = HumanName ("von Braun" )
320+ self .m (hn .first , "von" , hn )
321+ self .m (hn .last , "Braun" , hn )
322+
323+ def test_leading_van_is_unchanged (self ) -> None :
324+ hn = HumanName ("Van Johnson" )
325+ self .m (hn .first , "Van" , hn )
326+ self .m (hn .last , "Johnson" , hn )
327+
328+ def test_leading_della_is_unchanged (self ) -> None :
329+ hn = HumanName ("Della Reese" )
330+ self .m (hn .first , "Della" , hn )
331+ self .m (hn .last , "Reese" , hn )
332+
333+ def test_leading_di_is_unchanged (self ) -> None :
334+ hn = HumanName ("Di Caprio" )
335+ self .m (hn .first , "Di" , hn )
336+ self .m (hn .last , "Caprio" , hn )
337+
338+ def test_leading_del_is_unchanged (self ) -> None :
339+ hn = HumanName ("Del Toro" )
340+ self .m (hn .first , "Del" , hn )
341+ self .m (hn .last , "Toro" , hn )
342+
343+ def test_non_leading_prefix_is_unchanged (self ) -> None :
344+ hn = HumanName ("Jean de Mesnil" )
345+ self .m (hn .first , "Jean" , hn )
346+ self .m (hn .last , "de Mesnil" , hn )
347+
348+ # --- guard: bare particle with nothing to attach to ---
349+
350+ def test_bare_non_first_name_prefix_guard (self ) -> None :
351+ hn = HumanName ("de" )
352+ self .m (hn .first , "de" , hn )
353+ self .m (hn .last , "" , hn )
0 commit comments