From 0237bf09bf1fe70d94727b040ac39110f56b497f Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Sat, 25 Jan 2025 19:57:40 +0900 Subject: Split integration test file (#4205) --- test/test_preview.rb | 545 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 545 insertions(+) create mode 100644 test/test_preview.rb (limited to 'test/test_preview.rb') diff --git a/test/test_preview.rb b/test/test_preview.rb new file mode 100644 index 00000000..356d23a4 --- /dev/null +++ b/test/test_preview.rb @@ -0,0 +1,545 @@ +# frozen_string_literal: true + +require_relative 'lib/common' + +# Test cases for preview +class TestPreview < TestInteractive + def test_preview + tmux.send_keys %(seq 1000 | sed s/^2$// | #{FZF} -m --preview 'sleep 0.2; echo {{}-{+}}' --bind ?:toggle-preview), :Enter + tmux.until { |lines| assert_includes lines[1], ' {1-1} ' } + tmux.send_keys :Up + tmux.until { |lines| assert_includes lines[1], ' {-} ' } + tmux.send_keys '555' + tmux.until { |lines| assert_includes lines[1], ' {555-555} ' } + tmux.send_keys '?' + tmux.until { |lines| refute_includes lines[1], ' {555-555} ' } + tmux.send_keys '?' + tmux.until { |lines| assert_includes lines[1], ' {555-555} ' } + tmux.send_keys :BSpace + tmux.until { |lines| assert lines[-2]&.start_with?(' 28/1000 ') } + tmux.send_keys 'foobar' + tmux.until { |lines| refute_includes lines[1], ' {55-55} ' } + tmux.send_keys 'C-u' + tmux.until { |lines| assert_equal 1000, lines.match_count } + tmux.until { |lines| assert_includes lines[1], ' {1-1} ' } + tmux.send_keys :BTab + tmux.until { |lines| assert_includes lines[1], ' {-1} ' } + tmux.send_keys :BTab + tmux.until { |lines| assert_includes lines[1], ' {3-1 } ' } + tmux.send_keys :BTab + tmux.until { |lines| assert_includes lines[1], ' {4-1 3} ' } + tmux.send_keys :BTab + tmux.until { |lines| assert_includes lines[1], ' {5-1 3 4} ' } + end + + def test_toggle_preview_without_default_preview_command + tmux.send_keys %(seq 100 | #{FZF} --bind 'space:preview(echo [{}]),enter:toggle-preview' --preview-window up,border-double), :Enter + tmux.until do |lines| + assert_equal 100, lines.match_count + refute_includes lines[1], '║ [1]' + end + + # toggle-preview should do nothing + tmux.send_keys :Enter + tmux.until { |lines| refute_includes lines[1], '║ [1]' } + tmux.send_keys :Up + tmux.until do |lines| + refute_includes lines[1], '║ [1]' + refute_includes lines[1], '║ [2]' + end + + tmux.send_keys :Up + tmux.until do |lines| + assert_includes lines, '> 3' + refute_includes lines[1], '║ [3]' + end + + # One-off preview action + tmux.send_keys :Space + tmux.until { |lines| assert_includes lines[1], '║ [3]' } + + # toggle-preview to hide it + tmux.send_keys :Enter + tmux.until { |lines| refute_includes lines[1], '║ [3]' } + + # toggle-preview again does nothing + tmux.send_keys :Enter, :Up + tmux.until do |lines| + assert_includes lines, '> 4' + refute_includes lines[1], '║ [4]' + end + end + + def test_show_and_hide_preview + tmux.send_keys %(seq 100 | #{FZF} --preview-window hidden,border-bold --preview 'echo [{}]' --bind 'a:show-preview,b:hide-preview'), :Enter + + # Hidden by default + tmux.until do |lines| + assert_equal 100, lines.match_count + refute_includes lines[1], '┃ [1]' + end + + # Show + tmux.send_keys :a + tmux.until { |lines| assert_includes lines[1], '┃ [1]' } + + # Already shown + tmux.send_keys :a + tmux.send_keys :Up + tmux.until { |lines| assert_includes lines[1], '┃ [2]' } + + # Hide + tmux.send_keys :b + tmux.send_keys :Up + tmux.until do |lines| + assert_includes lines, '> 3' + refute_includes lines[1], '┃ [3]' + end + + # Already hidden + tmux.send_keys :b + tmux.send_keys :Up + tmux.until do |lines| + assert_includes lines, '> 4' + refute_includes lines[1], '┃ [4]' + end + + # Show it again + tmux.send_keys :a + tmux.until { |lines| assert_includes lines[1], '┃ [4]' } + end + + def test_preview_hidden + tmux.send_keys %(seq 1000 | #{FZF} --preview 'echo {{}-{}-$FZF_PREVIEW_LINES-$FZF_PREVIEW_COLUMNS}' --preview-window down:1:hidden --bind ?:toggle-preview), :Enter + tmux.until { |lines| assert_equal '>', lines[-1] } + tmux.send_keys '?' + tmux.until { |lines| assert_match(/ {1-1-1-[0-9]+}/, lines[-2]) } + tmux.send_keys '555' + tmux.until { |lines| assert_match(/ {555-555-1-[0-9]+}/, lines[-2]) } + tmux.send_keys '?' + tmux.until { |lines| assert_equal '> 555', lines[-1] } + end + + def test_preview_size_0 + tmux.send_keys %(seq 100 | #{FZF} --reverse --preview 'echo {} >> #{tempname}; echo ' --preview-window 0 --bind space:toggle-preview), :Enter + tmux.until do |lines| + assert_equal 100, lines.item_count + assert_equal ' 100/100', lines[1] + assert_equal '> 1', lines[2] + end + wait do + assert_path_exists tempname + assert_equal %w[1], File.readlines(tempname, chomp: true) + end + tmux.send_keys :Space, :Down, :Down + tmux.until { |lines| assert_equal '> 3', lines[4] } + wait do + assert_path_exists tempname + assert_equal %w[1], File.readlines(tempname, chomp: true) + end + tmux.send_keys :Space, :Down + tmux.until { |lines| assert_equal '> 4', lines[5] } + wait do + assert_path_exists tempname + assert_equal %w[1 3 4], File.readlines(tempname, chomp: true) + end + end + + def test_preview_size_0_hidden + tmux.send_keys %(seq 100 | #{FZF} --reverse --preview 'echo {} >> #{tempname}; echo ' --preview-window 0,hidden --bind space:toggle-preview), :Enter + tmux.until { |lines| assert_equal 100, lines.item_count } + tmux.send_keys :Down, :Down + tmux.until { |lines| assert_includes lines, '> 3' } + wait { refute_path_exists tempname } + tmux.send_keys :Space + wait do + assert_path_exists tempname + assert_equal %w[3], File.readlines(tempname, chomp: true) + end + tmux.send_keys :Down + wait do + assert_equal %w[3 4], File.readlines(tempname, chomp: true) + end + tmux.send_keys :Space, :Down + tmux.until { |lines| assert_includes lines, '> 5' } + tmux.send_keys :Down + tmux.until { |lines| assert_includes lines, '> 6' } + tmux.send_keys :Space + wait do + assert_equal %w[3 4 6], File.readlines(tempname, chomp: true) + end + end + + def test_preview_flags + tmux.send_keys %(seq 10 | sed 's/^/:: /; s/$/ /' | + #{FZF} --multi --preview 'echo {{2}/{s2}/{+2}/{+s2}/{q}/{n}/{+n}}'), :Enter + tmux.until { |lines| assert_includes lines[1], ' {1/1 /1/1 //0/0} ' } + tmux.send_keys '123' + tmux.until { |lines| assert_includes lines[1], ' {////123//} ' } + tmux.send_keys 'C-u', '1' + tmux.until { |lines| assert_equal 2, lines.match_count } + tmux.until { |lines| assert_includes lines[1], ' {1/1 /1/1 /1/0/0} ' } + tmux.send_keys :BTab + tmux.until { |lines| assert_includes lines[1], ' {10/10 /1/1 /1/9/0} ' } + tmux.send_keys :BTab + tmux.until { |lines| assert_includes lines[1], ' {10/10 /1 10/1 10 /1/9/0 9} ' } + tmux.send_keys '2' + tmux.until { |lines| assert_includes lines[1], ' {//1 10/1 10 /12//0 9} ' } + tmux.send_keys '3' + tmux.until { |lines| assert_includes lines[1], ' {//1 10/1 10 /123//0 9} ' } + end + + def test_preview_file + tmux.send_keys %[(echo foo bar; echo bar foo) | #{FZF} --multi --preview 'cat {+f} {+f2} {+nf} {+fn}' --print0], :Enter + tmux.until { |lines| assert_includes lines[1], ' foo barbar00 ' } + tmux.send_keys :BTab + tmux.until { |lines| assert_includes lines[1], ' foo barbar00 ' } + tmux.send_keys :BTab + tmux.until { |lines| assert_includes lines[1], ' foo barbar foobarfoo0101 ' } + end + + def test_preview_q_no_match + tmux.send_keys %(: | #{FZF} --preview 'echo foo {q} foo'), :Enter + tmux.until { |lines| assert_equal 0, lines.match_count } + tmux.until { |lines| assert_includes lines[1], ' foo foo' } + tmux.send_keys 'bar' + tmux.until { |lines| assert_includes lines[1], ' foo bar foo' } + tmux.send_keys 'C-u' + tmux.until { |lines| assert_includes lines[1], ' foo foo' } + end + + def test_preview_q_no_match_with_initial_query + tmux.send_keys %(: | #{FZF} --preview 'echo foo {q}{q}' --query foo), :Enter + tmux.until { |lines| assert_equal 0, lines.match_count } + tmux.until { |lines| assert_includes lines[1], ' foofoo ' } + end + + def test_preview_update_on_select + tmux.send_keys %(seq 10 | fzf -m --preview 'echo {+}' --bind a:toggle-all), + :Enter + tmux.until { |lines| assert_equal 10, lines.item_count } + tmux.send_keys 'a' + tmux.until { |lines| assert(lines.any? { |line| line.include?(' 1 2 3 4 5 ') }) } + tmux.send_keys 'a' + tmux.until { |lines| lines.each { |line| refute_includes line, ' 1 2 3 4 5 ' } } + end + + def test_preview_correct_tab_width_after_ansi_reset_code + writelines(["\x1b[31m+\x1b[m\t\x1b[32mgreen"]) + tmux.send_keys "#{FZF} --preview 'cat #{tempname}'", :Enter + tmux.until { |lines| assert_includes lines[1], ' + green ' } + end + + def test_preview_bindings_with_default_preview + tmux.send_keys "seq 10 | #{FZF} --preview 'echo [{}]' --bind 'a:preview(echo [{}{}]),b:preview(echo [{}{}{}]),c:refresh-preview'", :Enter + tmux.until { |lines| lines.item_count == 10 } + tmux.until { |lines| assert_includes lines[1], '[1]' } + tmux.send_keys 'a' + tmux.until { |lines| assert_includes lines[1], '[11]' } + tmux.send_keys 'c' + tmux.until { |lines| assert_includes lines[1], '[1]' } + tmux.send_keys 'b' + tmux.until { |lines| assert_includes lines[1], '[111]' } + tmux.send_keys :Up + tmux.until { |lines| assert_includes lines[1], '[2]' } + end + + def test_preview_bindings_without_default_preview + tmux.send_keys "seq 10 | #{FZF} --bind 'a:preview(echo [{}{}]),b:preview(echo [{}{}{}]),c:refresh-preview'", :Enter + tmux.until { |lines| lines.item_count == 10 } + tmux.until { |lines| refute_includes lines[1], '1' } + tmux.send_keys 'a' + tmux.until { |lines| assert_includes lines[1], '[11]' } + tmux.send_keys 'c' # does nothing + tmux.until { |lines| assert_includes lines[1], '[11]' } + tmux.send_keys 'b' + tmux.until { |lines| assert_includes lines[1], '[111]' } + tmux.send_keys 9 + tmux.until { |lines| lines.match_count == 1 } + tmux.until { |lines| refute_includes lines[1], '2' } + tmux.until { |lines| assert_includes lines[1], '[111]' } + end + + def test_preview_scroll_begin_constant + tmux.send_keys "echo foo 123 321 | #{FZF} --preview 'seq 1000' --preview-window left:+123", :Enter + tmux.until { |lines| assert_match %r{1/1}, lines[-2] } + tmux.until { |lines| assert_match %r{123.*123/1000}, lines[1] } + end + + def test_preview_scroll_begin_expr + tmux.send_keys "echo foo 123 321 | #{FZF} --preview 'seq 1000' --preview-window left:+{3}", :Enter + tmux.until { |lines| assert_match %r{1/1}, lines[-2] } + tmux.until { |lines| assert_match %r{321.*321/1000}, lines[1] } + end + + def test_preview_scroll_begin_and_offset + ['echo foo 123 321', 'echo foo :123: 321'].each do |input| + tmux.send_keys "#{input} | #{FZF} --preview 'seq 1000' --preview-window left:+{2}-2", :Enter + tmux.until { |lines| assert_match %r{1/1}, lines[-2] } + tmux.until { |lines| assert_match %r{121.*121/1000}, lines[1] } + tmux.send_keys 'C-c' + end + end + + def test_preview_clear_screen + tmux.send_keys %{seq 100 | #{FZF} --preview 'for i in $(seq 300); do (( i % 200 == 0 )) && printf "\\033[2J"; echo "[$i]"; sleep 0.001; done'}, :Enter + tmux.until { |lines| lines.item_count == 100 } + tmux.until { |lines| lines[1]&.include?('[200]') } + end + + def test_preview_window_follow + file = Tempfile.new('fzf-follow') + file.sync = true + + tmux.send_keys %(seq 100 | #{FZF} --preview 'echo start; tail -f "#{file.path}"' --preview-window follow --bind 'up:preview-up,down:preview-down,space:change-preview-window:follow|nofollow' --preview-window '~4'), :Enter + tmux.until { |lines| lines.item_count == 100 } + + # Write to the temporary file, and check if the preview window is showing + # the last line of the file + tmux.until { |lines| assert_includes lines[1], 'start' } + 3.times { file.puts _1 } # header lines + 1000.times { file.puts _1 } + tmux.until { |lines| assert_includes lines[1], '/1004' } + tmux.until { |lines| assert_includes lines[-2], '999' } + + # Scroll the preview window and fzf should stop following the file content + tmux.send_keys :Up + tmux.until { |lines| assert_includes lines[-2], '998' } + file.puts 'foo', 'bar' + tmux.until do |lines| + assert_includes lines[1], '/1006' + assert_includes lines[-2], '998' + end + + # Scroll back to the bottom and fzf should start following the file again + %w[999 foo bar].each do |item| + wait do + tmux.send_keys :Down + tmux.until { |lines| assert_includes lines[-2], item } + end + end + file.puts 'baz' + tmux.until do |lines| + assert_includes lines[1], '/1007' + assert_includes lines[-2], 'baz' + end + + # Scroll upwards to stop following + tmux.send_keys :Up + wait { assert_includes lines[-2], 'bar' } + file.puts 'aaa' + tmux.until do |lines| + assert_includes lines[1], '/1008' + assert_includes lines[-2], 'bar' + end + + # Manually enable following + tmux.send_keys :Space + tmux.until { |lines| assert_includes lines[-2], 'aaa' } + file.puts 'bbb' + tmux.until do |lines| + assert_includes lines[1], '/1009' + assert_includes lines[-2], 'bbb' + end + + # Disable following + tmux.send_keys :Space + file.puts 'ccc', 'ddd' + tmux.until do |lines| + assert_includes lines[1], '/1011' + assert_includes lines[-2], 'bbb' + end + rescue StandardError + file.close + file.unlink + end + + def test_toggle_preview_wrap + tmux.send_keys "#{FZF} --preview 'for i in $(seq $FZF_PREVIEW_COLUMNS); do echo -n .; done; echo wrapped; echo 2nd line' --bind ctrl-w:toggle-preview-wrap", :Enter + 2.times do + tmux.until { |lines| assert_includes lines[2], '2nd line' } + tmux.send_keys 'C-w' + tmux.until do |lines| + assert_includes lines[2], 'wrapped' + assert_includes lines[3], '2nd line' + end + tmux.send_keys 'C-w' + end + end + + def test_close + tmux.send_keys "seq 100 | #{FZF} --preview 'echo foo' --bind ctrl-c:close", :Enter + tmux.until { |lines| assert_equal 100, lines.match_count } + tmux.until { |lines| assert_includes lines[1], 'foo' } + tmux.send_keys 'C-c' + tmux.until { |lines| refute_includes lines[1], 'foo' } + tmux.send_keys '10' + tmux.until { |lines| assert_equal 2, lines.match_count } + tmux.send_keys 'C-c' + tmux.send_keys 'C-l', 'closed' + tmux.until { |lines| assert_includes lines[0], 'closed' } + end + + def test_preview_header + tmux.send_keys "seq 100 | #{FZF} --bind ctrl-k:preview-up+preview-up,ctrl-j:preview-down+preview-down+preview-down --preview 'seq 1000' --preview-window 'top:+{1}:~3'", :Enter + tmux.until { |lines| assert_equal 100, lines.item_count } + top5 = ->(lines) { lines.drop(1).take(5).map { |s| s[/[0-9]+/] } } + tmux.until do |lines| + assert_includes lines[1], '4/1000' + assert_equal(%w[1 2 3 4 5], top5[lines]) + end + tmux.send_keys '55' + tmux.until do |lines| + assert_equal 1, lines.match_count + assert_equal(%w[1 2 3 55 56], top5[lines]) + end + tmux.send_keys 'C-J' + tmux.until do |lines| + assert_equal(%w[1 2 3 58 59], top5[lines]) + end + tmux.send_keys :BSpace + tmux.until do |lines| + assert_equal 19, lines.match_count + assert_equal(%w[1 2 3 5 6], top5[lines]) + end + tmux.send_keys 'C-K' + tmux.until { |lines| assert_equal(%w[1 2 3 4 5], top5[lines]) } + end + + def test_change_preview_window + tmux.send_keys "seq 1000 | #{FZF} --preview 'echo [[{}]]' --no-preview-border --bind '" \ + 'a:change-preview(echo __{}__),' \ + 'b:change-preview-window(down)+change-preview(echo =={}==)+change-preview-window(up),' \ + 'c:change-preview(),d:change-preview-window(hidden),' \ + "e:preview(printf ::%${FZF_PREVIEW_COLUMNS}s{})+change-preview-window(up),f:change-preview-window(up,wrap)'", :Enter + tmux.until { |lines| assert_equal 1000, lines.item_count } + tmux.until { |lines| assert_includes lines[0], '[[1]]' } + + # change-preview action permanently changes the preview command set by --preview + tmux.send_keys 'a' + tmux.until { |lines| assert_includes lines[0], '__1__' } + tmux.send_keys :Up + tmux.until { |lines| assert_includes lines[0], '__2__' } + + # When multiple change-preview-window actions are bound to a single key, + # the last one wins and the updated options are immediately applied to the new preview + tmux.send_keys 'b' + tmux.until { |lines| assert_equal '==2==', lines[0] } + tmux.send_keys :Up + tmux.until { |lines| assert_equal '==3==', lines[0] } + + # change-preview with an empty preview command closes the preview window + tmux.send_keys 'c' + tmux.until { |lines| refute_includes lines[0], '==' } + + # change-preview again to re-open the preview window + tmux.send_keys 'a' + tmux.until { |lines| assert_equal '__3__', lines[0] } + + # Hide the preview window with hidden flag + tmux.send_keys 'd' + tmux.until { |lines| refute_includes lines[0], '__3__' } + + # One-off preview + tmux.send_keys 'e' + tmux.until do |lines| + assert_equal '::', lines[0] + refute_includes lines[1], '3' + end + + # Wrapped + tmux.send_keys 'f' + tmux.until do |lines| + assert_equal '::', lines[0] + assert_equal ' 3', lines[1] + end + end + + def test_change_preview_window_should_not_reset_change_preview + tmux.send_keys "#{FZF} --preview-window up,border-none --bind 'start:change-preview(echo hello)' --bind 'enter:change-preview-window(border-left)'", :Enter + tmux.until { |lines| assert_includes lines, 'hello' } + tmux.send_keys :Enter + tmux.until { |lines| assert_includes lines, '│ hello' } + end + + def test_change_preview_window_rotate + tmux.send_keys "seq 100 | #{FZF} --preview-window left,border-none --preview 'echo hello' --bind '" \ + "a:change-preview-window(right|down|up|hidden|)'", :Enter + tmux.until { |lines| assert(lines.any? { _1.include?('100/100') }) } + 3.times do + tmux.until { |lines| lines[0].start_with?('hello') } + tmux.send_keys 'a' + tmux.until { |lines| lines[0].end_with?('hello') } + tmux.send_keys 'a' + tmux.until { |lines| lines[-1].start_with?('hello') } + tmux.send_keys 'a' + tmux.until { |lines| assert_equal 'hello', lines[0] } + tmux.send_keys 'a' + tmux.until { |lines| refute_includes lines[0], 'hello' } + tmux.send_keys 'a' + end + end + + def test_change_preview_window_rotate_hidden + tmux.send_keys "seq 100 | #{FZF} --preview-window hidden --preview 'echo =={}==' --bind '" \ + "a:change-preview-window(nohidden||down,1|)'", :Enter + tmux.until { |lines| assert_equal 100, lines.match_count } + tmux.until { |lines| refute_includes lines[1], '==1==' } + tmux.send_keys 'a' + tmux.until { |lines| assert_includes lines[1], '==1==' } + tmux.send_keys 'a' + tmux.until { |lines| refute_includes lines[1], '==1==' } + tmux.send_keys 'a' + tmux.until { |lines| assert_includes lines[-2], '==1==' } + tmux.send_keys 'a' + tmux.until { |lines| refute_includes lines[-2], '==1==' } + tmux.send_keys 'a' + tmux.until { |lines| assert_includes lines[1], '==1==' } + end + + def test_change_preview_window_rotate_hidden_down + tmux.send_keys "seq 100 | #{FZF} --bind '?:change-preview-window:up||down|' --preview 'echo =={}==' --preview-window hidden,down,1", :Enter + tmux.until { |lines| assert_equal 100, lines.match_count } + tmux.until { |lines| refute_includes lines[1], '==1==' } + tmux.send_keys '?' + tmux.until { |lines| assert_includes lines[1], '==1==' } + tmux.send_keys '?' + tmux.until { |lines| refute_includes lines[1], '==1==' } + tmux.send_keys '?' + tmux.until { |lines| assert_includes lines[-2], '==1==' } + tmux.send_keys '?' + tmux.until { |lines| refute_includes lines[-2], '==1==' } + tmux.send_keys '?' + tmux.until { |lines| assert_includes lines[1], '==1==' } + end + + def test_toggle_alternative_preview_window + tmux.send_keys "seq 10 | #{FZF} --bind space:toggle-preview --preview-window '<100000(hidden,up,border-none)' --preview 'echo /{}/{}/'", :Enter + tmux.until { |lines| assert_equal 10, lines.item_count } + tmux.until { |lines| refute_includes lines, '/1/1/' } + tmux.send_keys :Space + tmux.until { |lines| assert_includes lines, '/1/1/' } + end + + def test_alternative_preview_window_opts + tmux.send_keys "seq 10 | #{FZF} --preview-window '~5,2,+0,<100000(~0,+100,wrap,noinfo)' --preview 'seq 1000'", :Enter + tmux.until { |lines| assert_equal 10, lines.item_count } + tmux.until do |lines| + assert_equal ['╭────╮', '│ 10 │', '│ 0 │', '│ 10 │', '│ 1 │'], lines.take(5).map(&:strip) + end + end + + def test_preview_window_width_exception + tmux.send_keys "seq 10 | #{FZF} --scrollbar --preview-window border-left --border --preview 'seq 1000'", :Enter + tmux.until do |lines| + assert lines[1]&.end_with?(' 1/1000││') + end + end + + def test_preview_window_hidden_on_focus + tmux.send_keys "seq 3 | #{FZF} --preview 'echo {}' --bind focus:hide-preview", :Enter + tmux.until { |lines| assert_includes lines, '> 1' } + tmux.send_keys :Up + tmux.until { |lines| assert_includes lines, '> 2' } + end +end -- cgit v1.2.3