@@ -284,3 +284,103 @@ describe('ui.focus_input', function()
284284 assert .same ({ 1 , 2 }, vim .api .nvim_win_get_cursor (input_win ))
285285 end )
286286end )
287+
288+ describe (' renderer._add_message_to_buffer scrolling' , function ()
289+ local renderer = require (' opencode.ui.renderer' )
290+ local formatter = require (' opencode.ui.formatter' )
291+ local stub = require (' luassert.stub' )
292+ local buf , win
293+
294+ before_each (function ()
295+ config .setup ({})
296+ buf = vim .api .nvim_create_buf (false , true )
297+ vim .api .nvim_buf_set_lines (buf , 0 , - 1 , false , { ' existing line' })
298+
299+ win = vim .api .nvim_open_win (buf , true , {
300+ relative = ' editor' , width = 80 , height = 10 , row = 0 , col = 0 ,
301+ })
302+
303+ state .windows = { output_win = win , output_buf = buf }
304+ state .active_session = { id = ' test-session' }
305+ state .messages = {}
306+ renderer ._prev_line_count = 1
307+ renderer ._render_state :reset ()
308+ end )
309+
310+ after_each (function ()
311+ pcall (vim .api .nvim_win_close , win , true )
312+ pcall (vim .api .nvim_buf_delete , buf , { force = true })
313+ state .windows = nil
314+ state .active_session = nil
315+ state .messages = nil
316+ renderer ._prev_line_count = 0
317+ renderer ._render_state :reset ()
318+ end )
319+
320+ it (' scrolls to bottom when user message is added' , function ()
321+ vim .api .nvim_win_set_cursor (win , { 1 , 0 })
322+
323+ local user_message = {
324+ info = {
325+ id = ' msg-1' ,
326+ sessionID = ' test-session' ,
327+ role = ' user' ,
328+ },
329+ parts = {},
330+ }
331+
332+ local scroll_called_with_force = false
333+ stub (renderer , ' scroll_to_bottom' ).invokes (function (force )
334+ scroll_called_with_force = force == true
335+ end )
336+
337+ renderer ._add_message_to_buffer (user_message )
338+
339+ assert .is_true (scroll_called_with_force )
340+ assert .stub (renderer .scroll_to_bottom ).was_called_with (true )
341+
342+ renderer .scroll_to_bottom :revert ()
343+ end )
344+
345+ it (' does not scroll when assistant message is added' , function ()
346+ vim .api .nvim_win_set_cursor (win , { 1 , 0 })
347+
348+ local assistant_message = {
349+ info = {
350+ id = ' msg-2' ,
351+ sessionID = ' test-session' ,
352+ role = ' assistant' ,
353+ },
354+ parts = {},
355+ }
356+
357+ stub (renderer , ' scroll_to_bottom' )
358+
359+ renderer ._add_message_to_buffer (assistant_message )
360+
361+ assert .stub (renderer .scroll_to_bottom ).was_not_called ()
362+
363+ renderer .scroll_to_bottom :revert ()
364+ end )
365+
366+ it (' does not scroll when system message is added' , function ()
367+ vim .api .nvim_win_set_cursor (win , { 1 , 0 })
368+
369+ local system_message = {
370+ info = {
371+ id = ' msg-3' ,
372+ sessionID = ' test-session' ,
373+ role = ' system' ,
374+ },
375+ parts = {},
376+ }
377+
378+ stub (renderer , ' scroll_to_bottom' )
379+
380+ renderer ._add_message_to_buffer (system_message )
381+
382+ assert .stub (renderer .scroll_to_bottom ).was_not_called ()
383+
384+ renderer .scroll_to_bottom :revert ()
385+ end )
386+ end )
0 commit comments