@@ -351,4 +351,286 @@ T["ui_preview"]["suggestion_preserves_on_movement_towards"] = function()
351
351
ref (child .get_screenshot ())
352
352
end
353
353
354
+ T [" ui_preview" ][" suggestion_history_basic_cycle" ] = function ()
355
+ set_content (" line1\n line2\n line3" )
356
+
357
+ -- Create first suggestion
358
+ local edit1 = {
359
+ range = {
360
+ start = { line = 1 , character = 0 },
361
+ [" end" ] = { line = 1 , character = 0 },
362
+ },
363
+ newText = " -- first suggestion" ,
364
+ }
365
+
366
+ -- Display first suggestion
367
+ child .g .test_edit = edit1
368
+ child .lua_func (function ()
369
+ local ns_id = vim .api .nvim_create_namespace (" nes_test" )
370
+ local edits = { vim .g .test_edit }
371
+ require (" copilot-lsp.nes.ui" )._display_next_suggestion (0 , ns_id , edits )
372
+ vim .uv .sleep (300 )
373
+ end )
374
+
375
+ -- Create and display second suggestion (should store first in history)
376
+ local edit2 = {
377
+ range = {
378
+ start = { line = 2 , character = 0 },
379
+ [" end" ] = { line = 2 , character = 0 },
380
+ },
381
+ newText = " -- second suggestion" ,
382
+ }
383
+
384
+ child .g .test_edit = edit2
385
+ child .lua_func (function ()
386
+ local ns_id = vim .api .nvim_create_namespace (" nes_test" )
387
+ local edits = { vim .g .test_edit }
388
+ require (" copilot-lsp.nes.ui" )._display_next_suggestion (0 , ns_id , edits )
389
+ vim .uv .sleep (300 )
390
+ end )
391
+
392
+ -- Clear current suggestion (second should now be in history too)
393
+ child .lua_func (function ()
394
+ local ns_id = vim .api .nvim_create_namespace (" nes_test" )
395
+ require (" copilot-lsp.nes.ui" ).clear_suggestion (0 , ns_id )
396
+ vim .uv .sleep (300 )
397
+ end )
398
+
399
+ -- First restore should show second suggestion (most recent)
400
+ local restored1 = child .lua_func (function ()
401
+ local ns_id = vim .api .nvim_create_namespace (" nes_test" )
402
+ local result = require (" copilot-lsp.nes.ui" ).restore_suggestion (0 , ns_id )
403
+ vim .uv .sleep (300 )
404
+ return result
405
+ end )
406
+ eq (restored1 , true )
407
+
408
+ -- Verify we can check history content
409
+ local history_size = child .lua_func (function ()
410
+ return # (vim .b [0 ].copilotlsp_nes_history or {})
411
+ end )
412
+ eq (history_size , 2 )
413
+
414
+ -- Second restore should show first suggestion
415
+ local restored2 = child .lua_func (function ()
416
+ local ns_id = vim .api .nvim_create_namespace (" nes_test" )
417
+ local restored = require (" copilot-lsp.nes.ui" ).restore_suggestion (0 , ns_id )
418
+ vim .uv .sleep (300 )
419
+ return restored
420
+ end )
421
+ eq (restored2 , true )
422
+
423
+ -- Third restore should cycle back to second suggestion
424
+ local restored3 = child .lua_func (function ()
425
+ local ns_id = vim .api .nvim_create_namespace (" nes_test" )
426
+ local restored = require (" copilot-lsp.nes.ui" ).restore_suggestion (0 , ns_id )
427
+ vim .uv .sleep (300 )
428
+ return restored
429
+ end )
430
+ eq (restored3 , true )
431
+ end
432
+
433
+ T [" ui_preview" ][" suggestion_history_max_two_items" ] = function ()
434
+ set_content (" line1\n line2\n line3\n line4" )
435
+
436
+ -- Create and display three suggestions
437
+ local suggestions = {
438
+ { newText = " -- first" , line = 0 },
439
+ { newText = " -- second" , line = 1 },
440
+ { newText = " -- third" , line = 2 },
441
+ }
442
+
443
+ for _ , suggestion in ipairs (suggestions ) do
444
+ local edit = {
445
+ range = {
446
+ start = { line = suggestion .line , character = 0 },
447
+ [" end" ] = { line = suggestion .line , character = 0 },
448
+ },
449
+ newText = suggestion .newText ,
450
+ }
451
+
452
+ child .g .test_edit = edit
453
+ child .lua_func (function ()
454
+ local ns_id = vim .api .nvim_create_namespace (" nes_test" )
455
+ local edits = { vim .g .test_edit }
456
+ require (" copilot-lsp.nes.ui" )._display_next_suggestion (0 , ns_id , edits )
457
+ vim .uv .sleep (300 )
458
+ end )
459
+ end
460
+
461
+ -- Clear current suggestion
462
+ child .lua_func (function ()
463
+ local ns_id = vim .api .nvim_create_namespace (" nes_test" )
464
+ require (" copilot-lsp.nes.ui" ).clear_suggestion (0 , ns_id )
465
+ vim .uv .sleep (300 )
466
+ end )
467
+
468
+ -- Verify history only keeps 2 most recent
469
+ local history_size = child .lua_func (function ()
470
+ return # (vim .b [0 ].copilotlsp_nes_history or {})
471
+ end )
472
+ eq (history_size , 2 )
473
+
474
+ -- Verify we can only cycle between 2 suggestions
475
+ local restore_results = {}
476
+ for _ = 1 , 4 do -- Try 4 restores to test cycling
477
+ local restored = child .lua_func (function ()
478
+ local ns_id = vim .api .nvim_create_namespace (" nes_test" )
479
+ return require (" copilot-lsp.nes.ui" ).restore_suggestion (0 , ns_id )
480
+ end )
481
+ table.insert (restore_results , restored )
482
+ vim .uv .sleep (300 )
483
+ end
484
+
485
+ -- All restores should succeed
486
+ for _ , result in ipairs (restore_results ) do
487
+ eq (result , true )
488
+ end
489
+ end
490
+
491
+ T [" ui_preview" ][" suggestion_history_invalid_after_text_changes" ] = function ()
492
+ set_content (" line1\n line2\n line3\n line4\n line5" )
493
+
494
+ -- Create suggestion on line 4 (0-indexed)
495
+ local edit = {
496
+ range = {
497
+ start = { line = 4 , character = 0 },
498
+ [" end" ] = { line = 4 , character = 0 },
499
+ },
500
+ newText = " -- comment on line 5" ,
501
+ }
502
+
503
+ child .g .test_edit = edit
504
+ child .lua_func (function ()
505
+ local ns_id = vim .api .nvim_create_namespace (" nes_test" )
506
+ local edits = { vim .g .test_edit }
507
+ require (" copilot-lsp.nes.ui" )._display_next_suggestion (0 , ns_id , edits )
508
+ vim .uv .sleep (300 )
509
+ end )
510
+
511
+ -- Clear suggestion to store in history
512
+ child .lua_func (function ()
513
+ local ns_id = vim .api .nvim_create_namespace (" nes_test" )
514
+ require (" copilot-lsp.nes.ui" ).clear_suggestion (0 , ns_id )
515
+ vim .uv .sleep (300 )
516
+ end )
517
+
518
+ -- Verify history exists
519
+ local history_size_before = child .lua_func (function ()
520
+ return # (vim .b [0 ].copilotlsp_nes_history or {})
521
+ end )
522
+ eq (history_size_before , 1 )
523
+
524
+ -- Delete lines to make history invalid (keep only first 3 lines)
525
+ child .api .nvim_buf_set_lines (0 , 3 , - 1 , false , {})
526
+
527
+ -- Try to restore (should fail and clear history)
528
+ local restored = child .lua_func (function ()
529
+ local ns_id = vim .api .nvim_create_namespace (" nes_test" )
530
+ local result = require (" copilot-lsp.nes.ui" ).restore_suggestion (0 , ns_id )
531
+ vim .uv .sleep (300 )
532
+ return result
533
+ end )
534
+ eq (restored , false )
535
+
536
+ -- Verify history was cleared
537
+ local history_size_after = child .lua_func (function ()
538
+ return # (vim .b [0 ].copilotlsp_nes_history or {})
539
+ end )
540
+ eq (history_size_after , 0 )
541
+ end
542
+
543
+ T [" ui_preview" ][" suggestion_history_restore_index_reset" ] = function ()
544
+ set_content (" line1\n line2\n line3" )
545
+ -- Create and display two suggestions to build history
546
+ local edit1 = {
547
+ range = {
548
+ start = { line = 1 , character = 0 },
549
+ [" end" ] = { line = 1 , character = 0 },
550
+ },
551
+ newText = " -- first" ,
552
+ }
553
+ local edit2 = {
554
+ range = {
555
+ start = { line = 2 , character = 0 },
556
+ [" end" ] = { line = 2 , character = 0 },
557
+ },
558
+ newText = " -- second" ,
559
+ }
560
+
561
+ -- Display first, then second (first goes to history)
562
+ child .g .test_edit = edit1
563
+ child .lua_func (function ()
564
+ local ns_id = vim .api .nvim_create_namespace (" nes_test" )
565
+ require (" copilot-lsp.nes.ui" )._display_next_suggestion (0 , ns_id , { vim .g .test_edit })
566
+ vim .uv .sleep (300 )
567
+ end )
568
+
569
+ child .g .test_edit = edit2
570
+ child .lua_func (function ()
571
+ local ns_id = vim .api .nvim_create_namespace (" nes_test" )
572
+ require (" copilot-lsp.nes.ui" )._display_next_suggestion (0 , ns_id , { vim .g .test_edit })
573
+ vim .uv .sleep (300 )
574
+ end )
575
+
576
+ -- Clear to add second to history
577
+ child .lua_func (function ()
578
+ local ns_id = vim .api .nvim_create_namespace (" nes_test" )
579
+ require (" copilot-lsp.nes.ui" ).clear_suggestion (0 , ns_id )
580
+ vim .uv .sleep (300 )
581
+ end )
582
+
583
+ -- Restore once (should show second, index becomes 1)
584
+ child .lua_func (function ()
585
+ local ns_id = vim .api .nvim_create_namespace (" nes_test" )
586
+ require (" copilot-lsp.nes.ui" ).restore_suggestion (0 , ns_id )
587
+ vim .uv .sleep (300 )
588
+ end )
589
+
590
+ -- Get restore index
591
+ local index_before = child .lua_func (function ()
592
+ return vim .b [0 ].copilotlsp_nes_restore_index or 0
593
+ end )
594
+ eq (index_before , 1 )
595
+
596
+ -- Display new suggestion (should reset index)
597
+ local edit3 = {
598
+ range = {
599
+ start = { line = 0 , character = 0 },
600
+ [" end" ] = { line = 0 , character = 0 },
601
+ },
602
+ newText = " -- third" ,
603
+ }
604
+
605
+ child .g .test_edit = edit3
606
+ child .lua_func (function ()
607
+ local ns_id = vim .api .nvim_create_namespace (" nes_test" )
608
+ require (" copilot-lsp.nes.ui" )._display_next_suggestion (0 , ns_id , { vim .g .test_edit })
609
+ vim .uv .sleep (300 )
610
+ end )
611
+
612
+ -- Verify index was reset
613
+ local index_after = child .lua_func (function ()
614
+ return vim .b [0 ].copilotlsp_nes_restore_index or 0
615
+ end )
616
+ eq (index_after , 0 )
617
+ end
618
+
619
+ T [" ui_preview" ][" suggestion_history_no_restore_when_empty" ] = function ()
620
+ set_content (" line1\n line2\n line3" )
621
+
622
+ -- Try to restore when no history exists
623
+ local restored = child .lua_func (function ()
624
+ local ns_id = vim .api .nvim_create_namespace (" nes_test" )
625
+ return require (" copilot-lsp.nes.ui" ).restore_suggestion (0 , ns_id )
626
+ end )
627
+ eq (restored , false )
628
+
629
+ -- Verify no history exists
630
+ local history_size = child .lua_func (function ()
631
+ return # (vim .b [0 ].copilotlsp_nes_history or {})
632
+ end )
633
+ eq (history_size , 0 )
634
+ end
635
+
354
636
return T
0 commit comments