@@ -81,7 +81,7 @@ pub(crate) struct BottomPaneParams {
81
81
}
82
82
83
83
impl BottomPane {
84
- const BOTTOM_PAD_LINES : u16 = 1 ;
84
+ const BOTTOM_PAD_LINES : u16 = 0 ;
85
85
pub fn new ( params : BottomPaneParams ) -> Self {
86
86
let enhanced_keys_supported = params. enhanced_keys_supported ;
87
87
Self {
@@ -522,10 +522,29 @@ impl WidgetRef for &BottomPane {
522
522
mod tests {
523
523
use super :: * ;
524
524
use crate :: app_event:: AppEvent ;
525
+ use insta:: assert_snapshot;
525
526
use ratatui:: buffer:: Buffer ;
526
527
use ratatui:: layout:: Rect ;
527
528
use tokio:: sync:: mpsc:: unbounded_channel;
528
529
530
+ fn snapshot_buffer ( buf : & Buffer ) -> String {
531
+ let mut lines = Vec :: new ( ) ;
532
+ for y in 0 ..buf. area ( ) . height {
533
+ let mut row = String :: new ( ) ;
534
+ for x in 0 ..buf. area ( ) . width {
535
+ row. push ( buf[ ( x, y) ] . symbol ( ) . chars ( ) . next ( ) . unwrap_or ( ' ' ) ) ;
536
+ }
537
+ lines. push ( row) ;
538
+ }
539
+ lines. join ( "\n " )
540
+ }
541
+
542
+ fn render_snapshot ( pane : & BottomPane , area : Rect ) -> String {
543
+ let mut buf = Buffer :: empty ( area) ;
544
+ ( & pane) . render_ref ( area, & mut buf) ;
545
+ snapshot_buffer ( & buf)
546
+ }
547
+
529
548
fn exec_request ( ) -> ApprovalRequest {
530
549
ApprovalRequest :: Exec {
531
550
id : "1" . to_string ( ) ,
@@ -685,7 +704,7 @@ mod tests {
685
704
}
686
705
687
706
#[ test]
688
- fn bottom_padding_present_with_status_above_composer ( ) {
707
+ fn status_and_composer_fill_height_without_bottom_padding ( ) {
689
708
let ( tx_raw, _rx) = unbounded_channel :: < AppEvent > ( ) ;
690
709
let tx = AppEventSender :: new ( tx_raw) ;
691
710
let mut pane = BottomPane :: new ( BottomPaneParams {
@@ -700,43 +719,21 @@ mod tests {
700
719
// Activate spinner (status view replaces composer) with no live ring.
701
720
pane. set_task_running ( true ) ;
702
721
703
- // Use height == desired_height; expect 1 status row at top and 2 bottom padding rows .
722
+ // Use height == desired_height; expect spacer + status + composer rows without trailing padding.
704
723
let height = pane. desired_height ( 30 ) ;
705
724
assert ! (
706
725
height >= 3 ,
707
- "expected at least 3 rows with bottom padding ; got {height}"
726
+ "expected at least 3 rows to render spacer, status, and composer ; got {height}"
708
727
) ;
709
728
let area = Rect :: new ( 0 , 0 , 30 , height) ;
710
- let mut buf = Buffer :: empty ( area) ;
711
- ( & pane) . render_ref ( area, & mut buf) ;
712
-
713
- // Row 1 contains the status header (row 0 is the spacer)
714
- let mut top = String :: new ( ) ;
715
- for x in 0 ..area. width {
716
- top. push ( buf[ ( x, 1 ) ] . symbol ( ) . chars ( ) . next ( ) . unwrap_or ( ' ' ) ) ;
717
- }
718
- assert ! (
719
- top. trim_start( ) . starts_with( "• Working" ) ,
720
- "expected top row to start with '• Working': {top:?}"
721
- ) ;
722
- assert ! (
723
- top. contains( "Working" ) ,
724
- "expected Working header on top row: {top:?}"
725
- ) ;
726
-
727
- // Last row should be blank padding; the row above should generally contain composer content.
728
- let mut r_last = String :: new ( ) ;
729
- for x in 0 ..area. width {
730
- r_last. push ( buf[ ( x, height - 1 ) ] . symbol ( ) . chars ( ) . next ( ) . unwrap_or ( ' ' ) ) ;
731
- }
732
- assert ! (
733
- r_last. trim( ) . is_empty( ) ,
734
- "expected last row blank: {r_last:?}"
729
+ assert_snapshot ! (
730
+ "status_and_composer_fill_height_without_bottom_padding" ,
731
+ render_snapshot( & pane, area)
735
732
) ;
736
733
}
737
734
738
735
#[ test]
739
- fn bottom_padding_shrinks_when_tiny ( ) {
736
+ fn status_hidden_when_height_too_small ( ) {
740
737
let ( tx_raw, _rx) = unbounded_channel :: < AppEvent > ( ) ;
741
738
let tx = AppEventSender :: new ( tx_raw) ;
742
739
let mut pane = BottomPane :: new ( BottomPaneParams {
@@ -750,37 +747,18 @@ mod tests {
750
747
751
748
pane. set_task_running ( true ) ;
752
749
753
- // Height=2 → status on one row, composer on the other .
750
+ // Height=2 → composer takes the full space; status collapses when there is no room .
754
751
let area2 = Rect :: new ( 0 , 0 , 20 , 2 ) ;
755
- let mut buf2 = Buffer :: empty ( area2) ;
756
- ( & pane) . render_ref ( area2, & mut buf2) ;
757
- let mut row0 = String :: new ( ) ;
758
- let mut row1 = String :: new ( ) ;
759
- for x in 0 ..area2. width {
760
- row0. push ( buf2[ ( x, 0 ) ] . symbol ( ) . chars ( ) . next ( ) . unwrap_or ( ' ' ) ) ;
761
- row1. push ( buf2[ ( x, 1 ) ] . symbol ( ) . chars ( ) . next ( ) . unwrap_or ( ' ' ) ) ;
762
- }
763
- let has_composer = row0. contains ( "Ask Codex" ) || row1. contains ( "Ask Codex" ) ;
764
- assert ! (
765
- has_composer,
766
- "expected composer to be visible on one of the rows: row0={row0:?}, row1={row1:?}"
767
- ) ;
768
- assert ! (
769
- row0. contains( "Working" ) || row1. contains( "Working" ) ,
770
- "expected status header to be visible at height=2: row0={row0:?}, row1={row1:?}"
752
+ assert_snapshot ! (
753
+ "status_hidden_when_height_too_small_height_2" ,
754
+ render_snapshot( & pane, area2)
771
755
) ;
772
756
773
757
// Height=1 → no padding; single row is the composer (status hidden).
774
758
let area1 = Rect :: new ( 0 , 0 , 20 , 1 ) ;
775
- let mut buf1 = Buffer :: empty ( area1) ;
776
- ( & pane) . render_ref ( area1, & mut buf1) ;
777
- let mut only = String :: new ( ) ;
778
- for x in 0 ..area1. width {
779
- only. push ( buf1[ ( x, 0 ) ] . symbol ( ) . chars ( ) . next ( ) . unwrap_or ( ' ' ) ) ;
780
- }
781
- assert ! (
782
- only. contains( "Ask Codex" ) ,
783
- "expected composer with no padding: {only:?}"
759
+ assert_snapshot ! (
760
+ "status_hidden_when_height_too_small_height_1" ,
761
+ render_snapshot( & pane, area1)
784
762
) ;
785
763
}
786
764
}
0 commit comments