@@ -44,7 +44,8 @@ afterAll(() => {
4444} ) ;
4545
4646describe ( "`useChatKeyboard` — Android behaviors" , ( ) => {
47- it ( "persistent inverted: should NOT reset padding on close" , ( ) => {
47+ it ( "persistent inverted: should always reset padding on close" , ( ) => {
48+ mockOffset . value = 500 ;
4849 const { result } = render ( {
4950 inverted : true ,
5051 keyboardLiftBehavior : "persistent" ,
@@ -54,10 +55,11 @@ describe("`useChatKeyboard` — Android behaviors", () => {
5455 handlers . onMove ( { height : KEYBOARD } ) ;
5556 handlers . onEnd ( { height : 0 } ) ;
5657
57- expect ( result . current . padding . value ) . toBe ( KEYBOARD ) ;
58+ expect ( result . current . padding . value ) . toBe ( 0 ) ;
5859 } ) ;
5960
60- it ( "persistent inverted: should not decrease shift" , ( ) => {
61+ it ( "persistent inverted: should not decrease shift when NOT at end" , ( ) => {
62+ mockOffset . value = 500 ;
6163 render ( {
6264 inverted : true ,
6365 keyboardLiftBehavior : "persistent" ,
@@ -68,12 +70,50 @@ describe("`useChatKeyboard` — Android behaviors", () => {
6870 expect ( mockScrollTo ) . toHaveBeenCalled ( ) ;
6971 mockScrollTo . mockClear ( ) ;
7072
71- // currentShift = offsetBeforeScroll(0 ) + padding(300) - scroll(0 ) = 300
72- // effective = 200 < 300 → return
73+ // currentShift = offsetBeforeScroll(500 ) + padding(300) - scroll(500 ) = 300
74+ // effective = 200 < 300 → return (not at end, so persistent holds)
7375 handlers . onMove ( { height : 200 } ) ;
7476 expect ( mockScrollTo ) . not . toHaveBeenCalled ( ) ;
7577 } ) ;
7678
79+ it ( "persistent inverted: should scrollTo on close when at end" , ( ) => {
80+ mockOffset . value = 0 ;
81+ render ( {
82+ inverted : true ,
83+ keyboardLiftBehavior : "persistent" ,
84+ } ) ;
85+
86+ handlers . onStart ( { height : KEYBOARD } ) ;
87+ handlers . onMove ( { height : KEYBOARD } ) ;
88+ mockScrollTo . mockClear ( ) ;
89+
90+ // Simulate keyboard closing
91+ handlers . onStart ( { height : 0 } ) ;
92+ // currentShift = 0 + 300 - 0 = 300, effective = 200 < 300
93+ // but at end → scrollTo called with snap to end
94+ handlers . onMove ( { height : 200 } ) ;
95+ expect ( mockScrollTo ) . toHaveBeenCalled ( ) ;
96+ } ) ;
97+
98+ it ( "persistent non-inverted: should scroll back on close when at end" , ( ) => {
99+ // Position at end: offset + layout >= content - threshold → 1200 + 800 >= 2000 - 20
100+ mockOffset . value = 1200 ;
101+ render ( { inverted : false , keyboardLiftBehavior : "persistent" } ) ;
102+
103+ handlers . onStart ( { height : KEYBOARD } ) ;
104+ handlers . onMove ( { height : KEYBOARD } ) ;
105+ mockScrollTo . mockClear ( ) ;
106+
107+ // Simulate keyboard closing (re-capture in onStart)
108+ // offsetBeforeScroll = scroll(1200) - padding(300) = 900
109+ // But wasAtEnd check uses offsetBeforeScroll + padding = 900 + 300 = 1200
110+ // isScrollAtEnd(1200, 800, 2000) = 1200 + 800 >= 1980 → true
111+ mockOffset . value = 1500 ;
112+ handlers . onStart ( { height : 0 } ) ;
113+ handlers . onMove ( { height : 200 } ) ;
114+ expect ( mockScrollTo ) . toHaveBeenCalled ( ) ;
115+ } ) ;
116+
77117 it ( "never non-inverted: should not scroll" , ( ) => {
78118 mockOffset . value = 100 ;
79119 render ( { inverted : false , keyboardLiftBehavior : "never" } ) ;
0 commit comments