@@ -447,3 +447,88 @@ def test_plot_xY_histogram_custom_colormap(synthetic_posterior_data):
447447 assert patch is None , "Histogram should not return PolyCollection"
448448
449449 plt .close (fig )
450+
451+
452+ @pytest .mark .integration
453+ def test_plot_xY_histogram_requires_single_time_dim ():
454+ """Histogram rejects Y with more than one non-chain/draw dimension."""
455+ rng = np .random .default_rng (0 )
456+ Y = xr .DataArray (
457+ rng .standard_normal ((2 , 30 , 4 , 5 )),
458+ dims = ["chain" , "draw" , "a" , "b" ],
459+ coords = {
460+ "chain" : [0 , 1 ],
461+ "draw" : np .arange (30 ),
462+ "a" : np .arange (4 ),
463+ "b" : np .arange (5 ),
464+ },
465+ )
466+ fig , ax = plt .subplots ()
467+ with pytest .raises (ValueError , match = "exactly one non-chain/draw" ):
468+ plot_xY (np .arange (4 ), Y , ax = ax , kind = "histogram" )
469+ plt .close (fig )
470+
471+
472+ @pytest .mark .integration
473+ def test_plot_xY_histogram_x_length_mismatch_raises (synthetic_posterior_data ):
474+ """Histogram rejects x length differing from the posterior time dimension."""
475+ x , Y = synthetic_posterior_data
476+ fig , ax = plt .subplots ()
477+ with pytest .raises (ValueError , match = "Length of x" ):
478+ plot_xY (x [:3 ], Y , ax = ax , kind = "histogram" )
479+ plt .close (fig )
480+
481+
482+ @pytest .mark .integration
483+ def test_plot_xY_histogram_single_time_point ():
484+ """Histogram with one time point exercises single-edge x bin construction."""
485+ rng = np .random .default_rng (2 )
486+ x = pd .date_range ("2020-01-01" , periods = 1 , freq = "D" )
487+ Y = xr .DataArray (
488+ rng .standard_normal ((2 , 40 , 1 )),
489+ dims = ["chain" , "draw" , "obs_ind" ],
490+ coords = {
491+ "chain" : [0 , 1 ],
492+ "draw" : np .arange (40 ),
493+ "obs_ind" : x ,
494+ },
495+ )
496+ fig , ax = plt .subplots ()
497+ handles , patch = plot_xY (x , Y , ax = ax , kind = "histogram" )
498+ assert isinstance (handles , list )
499+ assert patch is None
500+ plt .close (fig )
501+
502+
503+ @pytest .mark .integration
504+ def test_plot_xY_histogram_object_dtype_datetime_strings (synthetic_posterior_data ):
505+ """Object-dtype x of ISO strings hits datetime parsing in _x_as_numeric_mesh."""
506+ x , Y = synthetic_posterior_data
507+ x_obj = np .array ([str (t ) for t in x ], dtype = object )
508+ fig , ax = plt .subplots ()
509+ handles , patch = plot_xY (x_obj , Y , ax = ax , kind = "histogram" )
510+ assert isinstance (handles , list )
511+ assert patch is None
512+ plt .close (fig )
513+
514+
515+ @pytest .mark .integration
516+ def test_plot_xY_ribbon_fill_kwargs_eti (synthetic_posterior_data ):
517+ """Ribbon ETI path uses fill_kwargs and default label when label is None."""
518+ x , Y = synthetic_posterior_data
519+ fig , ax = plt .subplots ()
520+ h_line , h_patch = plot_xY (
521+ x ,
522+ Y ,
523+ ax = ax ,
524+ kind = "ribbon" ,
525+ ci_kind = "eti" ,
526+ plot_hdi_kwargs = {
527+ "color" : "C2" ,
528+ "fill_kwargs" : {"color" : "C2" , "alpha" : 0.4 },
529+ },
530+ label = None ,
531+ )
532+ assert isinstance (h_line , plt .Line2D )
533+ assert h_patch is not None
534+ plt .close (fig )
0 commit comments