mirror of
https://github.com/Llewellynvdm/fzf.git
synced 2025-02-01 19:48:31 +00:00
Split integration test file (#4205)
This commit is contained in:
parent
04017c25bb
commit
0237bf09bf
8
.github/workflows/linux.yml
vendored
8
.github/workflows/linux.yml
vendored
@ -30,19 +30,19 @@ jobs:
|
||||
- name: Setup Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: 3.1.0
|
||||
ruby-version: 3.4.1
|
||||
|
||||
- name: Install packages
|
||||
run: sudo apt-get install --yes zsh fish tmux
|
||||
|
||||
- name: Install Ruby gems
|
||||
run: sudo gem install --no-document minitest:5.25.1 rubocop:1.65.0 rubocop-minitest:0.35.1 rubocop-performance:1.21.1
|
||||
run: bundle install
|
||||
|
||||
- name: Rubocop
|
||||
run: rubocop --require rubocop-minitest --require rubocop-performance
|
||||
run: make lint
|
||||
|
||||
- name: Unit test
|
||||
run: make test
|
||||
|
||||
- name: Integration test
|
||||
run: make install && ./install --all && tmux new-session -d && ruby test/test_go.rb --verbose
|
||||
run: make install && ./install --all && tmux new-session -d && ruby test/runner.rb --verbose
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,7 +3,6 @@ bin/fzf.exe
|
||||
dist
|
||||
target
|
||||
pkg
|
||||
Gemfile.lock
|
||||
.DS_Store
|
||||
doc/tags
|
||||
vendor
|
||||
|
@ -1,3 +1,5 @@
|
||||
AllCops:
|
||||
NewCops: enable
|
||||
Layout/LineLength:
|
||||
Enabled: false
|
||||
Metrics:
|
||||
@ -28,5 +30,11 @@ Style/WordArray:
|
||||
MinSize: 1
|
||||
Minitest/AssertEqual:
|
||||
Enabled: false
|
||||
Minitest/EmptyLineBeforeAssertionMethods:
|
||||
Enabled: false
|
||||
Naming/VariableNumber:
|
||||
Enabled: false
|
||||
Lint/EmptyBlock:
|
||||
Enabled: false
|
||||
Style/SafeNavigationChainLength:
|
||||
Enabled: false
|
||||
|
@ -1 +1,2 @@
|
||||
golang 1.20.13
|
||||
ruby 3.4.1
|
||||
|
8
Gemfile
Normal file
8
Gemfile
Normal file
@ -0,0 +1,8 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
source 'https://rubygems.org'
|
||||
|
||||
gem 'minitest', '5.25.4'
|
||||
gem 'rubocop', '1.71.0'
|
||||
gem 'rubocop-minitest', '0.36.0'
|
||||
gem 'rubocop-performance', '1.23.1'
|
47
Gemfile.lock
Normal file
47
Gemfile.lock
Normal file
@ -0,0 +1,47 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
ast (2.4.2)
|
||||
json (2.9.1)
|
||||
language_server-protocol (3.17.0.3)
|
||||
minitest (5.25.4)
|
||||
parallel (1.26.3)
|
||||
parser (3.3.7.0)
|
||||
ast (~> 2.4.1)
|
||||
racc
|
||||
racc (1.8.1)
|
||||
rainbow (3.1.1)
|
||||
regexp_parser (2.10.0)
|
||||
rubocop (1.71.0)
|
||||
json (~> 2.3)
|
||||
language_server-protocol (>= 3.17.0)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 3.3.0.2)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
regexp_parser (>= 2.9.3, < 3.0)
|
||||
rubocop-ast (>= 1.36.2, < 2.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 2.4.0, < 4.0)
|
||||
rubocop-ast (1.37.0)
|
||||
parser (>= 3.3.1.0)
|
||||
rubocop-minitest (0.36.0)
|
||||
rubocop (>= 1.61, < 2.0)
|
||||
rubocop-ast (>= 1.31.1, < 2.0)
|
||||
rubocop-performance (1.23.1)
|
||||
rubocop (>= 1.48.1, < 2.0)
|
||||
rubocop-ast (>= 1.31.1, < 2.0)
|
||||
ruby-progressbar (1.13.0)
|
||||
unicode-display_width (2.6.0)
|
||||
|
||||
PLATFORMS
|
||||
arm64-darwin-23
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
minitest (= 5.25.4)
|
||||
rubocop (= 1.71.0)
|
||||
rubocop-minitest (= 0.36.0)
|
||||
rubocop-performance (= 1.23.1)
|
||||
|
||||
BUNDLED WITH
|
||||
2.6.2
|
9
Makefile
9
Makefile
@ -82,12 +82,15 @@ test: $(SOURCES)
|
||||
github.com/junegunn/fzf/src/tui \
|
||||
github.com/junegunn/fzf/src/util
|
||||
|
||||
itest:
|
||||
ruby test/runner.rb
|
||||
|
||||
bench:
|
||||
cd src && SHELL=/bin/sh GOOS= $(GO) test -v -tags "$(TAGS)" -run=Bench -bench=. -benchmem
|
||||
|
||||
lint: $(SOURCES) test/test_go.rb
|
||||
lint: $(SOURCES) test/*.rb test/lib/*.rb
|
||||
[ -z "$$(gofmt -s -d src)" ] || (gofmt -s -d src; exit 1)
|
||||
rubocop --require rubocop-minitest --require rubocop-performance
|
||||
bundle exec rubocop -a --require rubocop-minitest --require rubocop-performance
|
||||
|
||||
install: bin/fzf
|
||||
|
||||
@ -186,4 +189,4 @@ update:
|
||||
$(GO) get -u
|
||||
$(GO) mod tidy
|
||||
|
||||
.PHONY: all generate build release test bench lint install clean docker docker-test update
|
||||
.PHONY: all generate build release test itest bench lint install clean docker docker-test update
|
||||
|
240
test/lib/common.rb
Normal file
240
test/lib/common.rb
Normal file
@ -0,0 +1,240 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'bundler/setup'
|
||||
require 'minitest/autorun'
|
||||
require 'fileutils'
|
||||
require 'English'
|
||||
require 'shellwords'
|
||||
require 'erb'
|
||||
require 'tempfile'
|
||||
require 'net/http'
|
||||
require 'json'
|
||||
|
||||
TEMPLATE = File.read(File.expand_path('common.sh', __dir__))
|
||||
UNSETS = %w[
|
||||
FZF_DEFAULT_COMMAND FZF_DEFAULT_OPTS
|
||||
FZF_TMUX FZF_TMUX_OPTS
|
||||
FZF_CTRL_T_COMMAND FZF_CTRL_T_OPTS
|
||||
FZF_ALT_C_COMMAND
|
||||
FZF_ALT_C_OPTS FZF_CTRL_R_OPTS
|
||||
FZF_API_KEY
|
||||
].freeze
|
||||
DEFAULT_TIMEOUT = 10
|
||||
|
||||
FILE = File.expand_path(__FILE__)
|
||||
BASE = File.expand_path('../..', __dir__)
|
||||
Dir.chdir(BASE)
|
||||
FZF = "FZF_DEFAULT_OPTS=\"--no-scrollbar --pointer \\> --marker \\>\" FZF_DEFAULT_COMMAND= #{BASE}/bin/fzf".freeze
|
||||
|
||||
def wait(timeout = DEFAULT_TIMEOUT)
|
||||
since = Time.now
|
||||
begin
|
||||
yield or raise Minitest::Assertion, 'Assertion failure'
|
||||
rescue Minitest::Assertion
|
||||
raise if Time.now - since > timeout
|
||||
|
||||
sleep(0.05)
|
||||
retry
|
||||
end
|
||||
end
|
||||
|
||||
class Shell
|
||||
class << self
|
||||
def bash
|
||||
@bash ||=
|
||||
begin
|
||||
bashrc = '/tmp/fzf.bash'
|
||||
File.open(bashrc, 'w') do |f|
|
||||
f.puts ERB.new(TEMPLATE).result(binding)
|
||||
end
|
||||
|
||||
"bash --rcfile #{bashrc}"
|
||||
end
|
||||
end
|
||||
|
||||
def zsh
|
||||
@zsh ||=
|
||||
begin
|
||||
zdotdir = '/tmp/fzf-zsh'
|
||||
FileUtils.rm_rf(zdotdir)
|
||||
FileUtils.mkdir_p(zdotdir)
|
||||
File.open("#{zdotdir}/.zshrc", 'w') do |f|
|
||||
f.puts ERB.new(TEMPLATE).result(binding)
|
||||
end
|
||||
"ZDOTDIR=#{zdotdir} zsh"
|
||||
end
|
||||
end
|
||||
|
||||
def fish
|
||||
"unset #{UNSETS.join(' ')}; rm -f ~/.local/share/fish/fzf_test_history; FZF_DEFAULT_OPTS=\"--no-scrollbar --pointer '>' --marker '>'\" fish_history=fzf_test fish"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Tmux
|
||||
attr_reader :win
|
||||
|
||||
def initialize(shell = :bash)
|
||||
@win = go(%W[new-window -d -P -F #I #{Shell.send(shell)}]).first
|
||||
go(%W[set-window-option -t #{@win} pane-base-index 0])
|
||||
return unless shell == :fish
|
||||
|
||||
send_keys 'function fish_prompt; end; clear', :Enter
|
||||
self.until(&:empty?)
|
||||
end
|
||||
|
||||
def kill
|
||||
go(%W[kill-window -t #{win}])
|
||||
end
|
||||
|
||||
def focus
|
||||
go(%W[select-window -t #{win}])
|
||||
end
|
||||
|
||||
def send_keys(*args)
|
||||
go(%W[send-keys -t #{win}] + args.map(&:to_s))
|
||||
end
|
||||
|
||||
def paste(str)
|
||||
system('tmux', 'setb', str, ';', 'pasteb', '-t', win, ';', 'send-keys', '-t', win, 'Enter')
|
||||
end
|
||||
|
||||
def capture
|
||||
go(%W[capture-pane -p -J -t #{win}]).map(&:rstrip).reverse.drop_while(&:empty?).reverse
|
||||
end
|
||||
|
||||
def until(refresh = false, timeout: DEFAULT_TIMEOUT)
|
||||
lines = nil
|
||||
begin
|
||||
wait(timeout) do
|
||||
lines = capture
|
||||
class << lines
|
||||
def counts
|
||||
lazy
|
||||
.map { |l| l.scan(%r{^. ([0-9]+)/([0-9]+)( \(([0-9]+)\))?}) }
|
||||
.reject(&:empty?)
|
||||
.first&.first&.map(&:to_i)&.values_at(0, 1, 3) || [0, 0, 0]
|
||||
end
|
||||
|
||||
def match_count
|
||||
counts[0]
|
||||
end
|
||||
|
||||
def item_count
|
||||
counts[1]
|
||||
end
|
||||
|
||||
def select_count
|
||||
counts[2]
|
||||
end
|
||||
|
||||
def any_include?(val)
|
||||
method = val.is_a?(Regexp) ? :match : :include?
|
||||
find { |line| line.send(method, val) }
|
||||
end
|
||||
end
|
||||
yield(lines).tap do |ok|
|
||||
send_keys 'C-l' if refresh && !ok
|
||||
end
|
||||
end
|
||||
rescue Minitest::Assertion
|
||||
puts $ERROR_INFO.backtrace
|
||||
puts '>' * 80
|
||||
puts lines
|
||||
puts '<' * 80
|
||||
raise
|
||||
end
|
||||
lines
|
||||
end
|
||||
|
||||
def prepare
|
||||
tries = 0
|
||||
begin
|
||||
self.until(true) do |lines|
|
||||
message = "Prepare[#{tries}]"
|
||||
send_keys ' ', 'C-u', :Enter, message, :Left, :Right
|
||||
lines[-1] == message
|
||||
end
|
||||
rescue Minitest::Assertion
|
||||
(tries += 1) < 5 ? retry : raise
|
||||
end
|
||||
send_keys 'C-u', 'C-l'
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def go(args)
|
||||
IO.popen(%w[tmux] + args) { |io| io.readlines(chomp: true) }
|
||||
end
|
||||
end
|
||||
|
||||
class TestBase < Minitest::Test
|
||||
TEMPNAME = Dir::Tmpname.create(%w[fzf]) {}
|
||||
FIFONAME = Dir::Tmpname.create(%w[fzf-fifo]) {}
|
||||
|
||||
def writelines(lines)
|
||||
File.write(TEMPNAME, lines.join("\n"))
|
||||
end
|
||||
|
||||
def tempname
|
||||
TEMPNAME
|
||||
end
|
||||
|
||||
def fzf_output
|
||||
@thread.join.value.chomp.tap { @thread = nil }
|
||||
end
|
||||
|
||||
def fzf_output_lines
|
||||
fzf_output.lines(chomp: true)
|
||||
end
|
||||
|
||||
def setup
|
||||
File.mkfifo(FIFONAME)
|
||||
end
|
||||
|
||||
def teardown
|
||||
FileUtils.rm_f([TEMPNAME, FIFONAME])
|
||||
end
|
||||
|
||||
alias assert_equal_org assert_equal
|
||||
def assert_equal(expected, actual)
|
||||
# Ignore info separator
|
||||
actual = actual&.sub(/\s*─+$/, '') if actual.is_a?(String) && actual&.match?(%r{\d+/\d+})
|
||||
assert_equal_org(expected, actual)
|
||||
end
|
||||
|
||||
# Run fzf with its output piped to a fifo
|
||||
def fzf(*opts)
|
||||
raise 'fzf_output not taken' if @thread
|
||||
|
||||
@thread = Thread.new { File.read(FIFONAME) }
|
||||
fzf!(*opts) + " > #{FIFONAME.shellescape}"
|
||||
end
|
||||
|
||||
def fzf!(*opts)
|
||||
opts = opts.filter_map do |o|
|
||||
case o
|
||||
when Symbol
|
||||
o = o.to_s
|
||||
o.length > 1 ? "--#{o.tr('_', '-')}" : "-#{o}"
|
||||
when String, Numeric
|
||||
o.to_s
|
||||
end
|
||||
end
|
||||
"#{FZF} #{opts.join(' ')}"
|
||||
end
|
||||
end
|
||||
|
||||
class TestInteractive < TestBase
|
||||
attr_reader :tmux
|
||||
|
||||
def setup
|
||||
super
|
||||
@tmux = Tmux.new
|
||||
end
|
||||
|
||||
def teardown
|
||||
super
|
||||
@tmux.kill
|
||||
end
|
||||
end
|
59
test/lib/common.sh
Normal file
59
test/lib/common.sh
Normal file
@ -0,0 +1,59 @@
|
||||
set -u
|
||||
PS1= PROMPT_COMMAND= HISTFILE= HISTSIZE=100
|
||||
unset <%= UNSETS.join(' ') %>
|
||||
unset $(env | sed -n /^_fzf_orig/s/=.*//p)
|
||||
unset $(declare -F | sed -n "/_fzf/s/.*-f //p")
|
||||
|
||||
export FZF_DEFAULT_OPTS="--no-scrollbar --pointer '>' --marker '>'"
|
||||
|
||||
# Setup fzf
|
||||
# ---------
|
||||
if [[ ! "$PATH" == *<%= BASE %>/bin* ]]; then
|
||||
export PATH="${PATH:+${PATH}:}<%= BASE %>/bin"
|
||||
fi
|
||||
|
||||
# Auto-completion
|
||||
# ---------------
|
||||
[[ $- == *i* ]] && source "<%= BASE %>/shell/completion.<%= __method__ %>" 2> /dev/null
|
||||
|
||||
# Key bindings
|
||||
# ------------
|
||||
source "<%= BASE %>/shell/key-bindings.<%= __method__ %>"
|
||||
|
||||
# Old API
|
||||
_fzf_complete_f() {
|
||||
_fzf_complete "+m --multi --prompt \"prompt-f> \"" "$@" < <(
|
||||
echo foo
|
||||
echo bar
|
||||
)
|
||||
}
|
||||
|
||||
# New API
|
||||
_fzf_complete_g() {
|
||||
_fzf_complete +m --multi --prompt "prompt-g> " -- "$@" < <(
|
||||
echo foo
|
||||
echo bar
|
||||
)
|
||||
}
|
||||
|
||||
_fzf_complete_f_post() {
|
||||
awk '{print "f" $0 $0}'
|
||||
}
|
||||
|
||||
_fzf_complete_g_post() {
|
||||
awk '{print "g" $0 $0}'
|
||||
}
|
||||
|
||||
[ -n "${BASH-}" ] && complete -F _fzf_complete_f -o default -o bashdefault f
|
||||
[ -n "${BASH-}" ] && complete -F _fzf_complete_g -o default -o bashdefault g
|
||||
|
||||
_comprun() {
|
||||
local command=$1
|
||||
shift
|
||||
|
||||
case "$command" in
|
||||
f) fzf "$@" --preview 'echo preview-f-{}' ;;
|
||||
g) fzf "$@" --preview 'echo preview-g-{}' ;;
|
||||
*) fzf "$@" ;;
|
||||
esac
|
||||
}
|
5
test/runner.rb
Normal file
5
test/runner.rb
Normal file
@ -0,0 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
Dir[File.join(__dir__, 'test_*.rb')].each { require it }
|
||||
|
||||
require 'minitest/autorun'
|
1588
test/test_core.rb
Normal file
1588
test/test_core.rb
Normal file
File diff suppressed because it is too large
Load Diff
417
test/test_exec.rb
Normal file
417
test/test_exec.rb
Normal file
@ -0,0 +1,417 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'lib/common'
|
||||
|
||||
# Process execution: execute, become, reload
|
||||
class TestExec < TestInteractive
|
||||
def test_execute
|
||||
output = '/tmp/fzf-test-execute'
|
||||
opts = %[--bind "alt-a:execute(echo /{}/ >> #{output})+change-header(alt-a),alt-b:execute[echo /{}{}/ >> #{output}]+change-header(alt-b),C:execute(echo /{}{}{}/ >> #{output})+change-header(C)"]
|
||||
writelines(%w[foo'bar foo"bar foo$bar])
|
||||
tmux.send_keys "cat #{tempname} | #{FZF} #{opts}", :Enter
|
||||
tmux.until { |lines| assert_equal 3, lines.item_count }
|
||||
|
||||
ready = ->(s) { tmux.until { |lines| assert_includes lines[-3], s } }
|
||||
tmux.send_keys :Escape, :a
|
||||
ready.call('alt-a')
|
||||
tmux.send_keys :Escape, :b
|
||||
ready.call('alt-b')
|
||||
|
||||
tmux.send_keys :Up
|
||||
tmux.send_keys :Escape, :a
|
||||
ready.call('alt-a')
|
||||
tmux.send_keys :Escape, :b
|
||||
ready.call('alt-b')
|
||||
|
||||
tmux.send_keys :Up
|
||||
tmux.send_keys :C
|
||||
ready.call('C')
|
||||
|
||||
tmux.send_keys 'barfoo'
|
||||
tmux.until { |lines| assert_equal ' 0/3', lines[-2] }
|
||||
|
||||
tmux.send_keys :Escape, :a
|
||||
ready.call('alt-a')
|
||||
tmux.send_keys :Escape, :b
|
||||
ready.call('alt-b')
|
||||
|
||||
wait do
|
||||
assert_path_exists output
|
||||
assert_equal %w[
|
||||
/foo'bar/ /foo'barfoo'bar/
|
||||
/foo"bar/ /foo"barfoo"bar/
|
||||
/foo$barfoo$barfoo$bar/
|
||||
], File.readlines(output, chomp: true)
|
||||
end
|
||||
ensure
|
||||
FileUtils.rm_f(output)
|
||||
end
|
||||
|
||||
def test_execute_multi
|
||||
output = '/tmp/fzf-test-execute-multi'
|
||||
opts = %[--multi --bind "alt-a:execute-multi(echo {}/{+} >> #{output})+change-header(alt-a),alt-b:change-header(alt-b)"]
|
||||
writelines(%w[foo'bar foo"bar foo$bar foobar])
|
||||
tmux.send_keys "cat #{tempname} | #{FZF} #{opts}", :Enter
|
||||
ready = ->(s) { tmux.until { |lines| assert_includes lines[-3], s } }
|
||||
|
||||
tmux.until { |lines| assert_equal ' 4/4 (0)', lines[-2] }
|
||||
tmux.send_keys :Escape, :a
|
||||
ready.call('alt-a')
|
||||
tmux.send_keys :Escape, :b
|
||||
ready.call('alt-b')
|
||||
|
||||
tmux.send_keys :BTab, :BTab, :BTab
|
||||
tmux.until { |lines| assert_equal ' 4/4 (3)', lines[-2] }
|
||||
tmux.send_keys :Escape, :a
|
||||
ready.call('alt-a')
|
||||
tmux.send_keys :Escape, :b
|
||||
ready.call('alt-b')
|
||||
|
||||
tmux.send_keys :Tab, :Tab
|
||||
tmux.until { |lines| assert_equal ' 4/4 (3)', lines[-2] }
|
||||
tmux.send_keys :Escape, :a
|
||||
ready.call('alt-a')
|
||||
wait do
|
||||
assert_path_exists output
|
||||
assert_equal [
|
||||
%(foo'bar/foo'bar),
|
||||
%(foo'bar foo"bar foo$bar/foo'bar foo"bar foo$bar),
|
||||
%(foo'bar foo"bar foobar/foo'bar foo"bar foobar)
|
||||
], File.readlines(output, chomp: true)
|
||||
end
|
||||
ensure
|
||||
FileUtils.rm_f(output)
|
||||
end
|
||||
|
||||
def test_execute_plus_flag
|
||||
output = tempname + '.tmp'
|
||||
FileUtils.rm_f(output)
|
||||
writelines(['foo bar', '123 456'])
|
||||
|
||||
tmux.send_keys "cat #{tempname} | #{FZF} --multi --bind 'x:execute-silent(echo {+}/{}/{+2}/{2} >> #{output})'", :Enter
|
||||
|
||||
tmux.until { |lines| assert_equal ' 2/2 (0)', lines[-2] }
|
||||
tmux.send_keys 'xy'
|
||||
tmux.until { |lines| assert_equal ' 0/2 (0)', lines[-2] }
|
||||
tmux.send_keys :BSpace
|
||||
tmux.until { |lines| assert_equal ' 2/2 (0)', lines[-2] }
|
||||
|
||||
tmux.send_keys :Up
|
||||
tmux.send_keys :Tab
|
||||
tmux.send_keys 'xy'
|
||||
tmux.until { |lines| assert_equal ' 0/2 (1)', lines[-2] }
|
||||
tmux.send_keys :BSpace
|
||||
tmux.until { |lines| assert_equal ' 2/2 (1)', lines[-2] }
|
||||
|
||||
tmux.send_keys :Tab
|
||||
tmux.send_keys 'xy'
|
||||
tmux.until { |lines| assert_equal ' 0/2 (2)', lines[-2] }
|
||||
tmux.send_keys :BSpace
|
||||
tmux.until { |lines| assert_equal ' 2/2 (2)', lines[-2] }
|
||||
|
||||
wait do
|
||||
assert_path_exists output
|
||||
assert_equal [
|
||||
%(foo bar/foo bar/bar/bar),
|
||||
%(123 456/foo bar/456/bar),
|
||||
%(123 456 foo bar/foo bar/456 bar/bar)
|
||||
], File.readlines(output, chomp: true)
|
||||
end
|
||||
rescue StandardError
|
||||
FileUtils.rm_f(output)
|
||||
end
|
||||
|
||||
def test_execute_shell
|
||||
# Custom script to use as $SHELL
|
||||
output = tempname + '.out'
|
||||
FileUtils.rm_f(output)
|
||||
writelines(['#!/usr/bin/env bash', "echo $1 / $2 > #{output}"])
|
||||
system("chmod +x #{tempname}")
|
||||
|
||||
tmux.send_keys "echo foo | SHELL=#{tempname} fzf --bind 'enter:execute:{}bar'", :Enter
|
||||
tmux.until { |lines| assert_equal ' 1/1', lines[-2] }
|
||||
tmux.send_keys :Enter
|
||||
tmux.until { |lines| assert_equal ' 1/1', lines[-2] }
|
||||
wait do
|
||||
assert_path_exists output
|
||||
assert_equal ["-c / 'foo'bar"], File.readlines(output, chomp: true)
|
||||
end
|
||||
ensure
|
||||
FileUtils.rm_f(output)
|
||||
end
|
||||
|
||||
def test_interrupt_execute
|
||||
tmux.send_keys "seq 100 | #{FZF} --bind 'ctrl-l:execute:echo executing {}; sleep 100'", :Enter
|
||||
tmux.until { |lines| assert_equal 100, lines.item_count }
|
||||
tmux.send_keys 'C-l'
|
||||
tmux.until { |lines| assert lines.any_include?('executing 1') }
|
||||
tmux.send_keys 'C-c'
|
||||
tmux.until { |lines| assert_equal 100, lines.item_count }
|
||||
tmux.send_keys 99
|
||||
tmux.until { |lines| assert_equal 1, lines.match_count }
|
||||
end
|
||||
|
||||
def test_kill_default_command_on_abort
|
||||
writelines(['#!/usr/bin/env bash',
|
||||
"echo 'Started'",
|
||||
'while :; do sleep 1; done'])
|
||||
system("chmod +x #{tempname}")
|
||||
|
||||
tmux.send_keys FZF.sub('FZF_DEFAULT_COMMAND=', "FZF_DEFAULT_COMMAND=#{tempname}"), :Enter
|
||||
tmux.until { |lines| assert_equal 1, lines.item_count }
|
||||
tmux.send_keys 'C-c'
|
||||
tmux.send_keys 'C-l', 'closed'
|
||||
tmux.until { |lines| assert_includes lines[0], 'closed' }
|
||||
wait { refute system("pgrep -f #{tempname}") }
|
||||
ensure
|
||||
system("pkill -9 -f #{tempname}")
|
||||
end
|
||||
|
||||
def test_kill_default_command_on_accept
|
||||
writelines(['#!/usr/bin/env bash',
|
||||
"echo 'Started'",
|
||||
'while :; do sleep 1; done'])
|
||||
system("chmod +x #{tempname}")
|
||||
|
||||
tmux.send_keys fzf.sub('FZF_DEFAULT_COMMAND=', "FZF_DEFAULT_COMMAND=#{tempname}"), :Enter
|
||||
tmux.until { |lines| assert_equal 1, lines.match_count }
|
||||
tmux.send_keys :Enter
|
||||
assert_equal 'Started', fzf_output
|
||||
wait { refute system("pgrep -f #{tempname}") }
|
||||
ensure
|
||||
system("pkill -9 -f #{tempname}")
|
||||
end
|
||||
|
||||
def test_kill_reload_command_on_abort
|
||||
writelines(['#!/usr/bin/env bash',
|
||||
"echo 'Started'",
|
||||
'while :; do sleep 1; done'])
|
||||
system("chmod +x #{tempname}")
|
||||
|
||||
tmux.send_keys "seq 1 3 | #{FZF} --bind 'ctrl-r:reload(#{tempname})'", :Enter
|
||||
tmux.until { |lines| assert_equal 3, lines.item_count }
|
||||
tmux.send_keys 'C-r'
|
||||
tmux.until { |lines| assert_equal 1, lines.item_count }
|
||||
tmux.send_keys 'C-c'
|
||||
tmux.send_keys 'C-l', 'closed'
|
||||
tmux.until { |lines| assert_includes lines[0], 'closed' }
|
||||
wait { refute system("pgrep -f #{tempname}") }
|
||||
ensure
|
||||
system("pkill -9 -f #{tempname}")
|
||||
end
|
||||
|
||||
def test_kill_reload_command_on_accept
|
||||
writelines(['#!/usr/bin/env bash',
|
||||
"echo 'Started'",
|
||||
'while :; do sleep 1; done'])
|
||||
system("chmod +x #{tempname}")
|
||||
|
||||
tmux.send_keys "seq 1 3 | #{fzf("--bind 'ctrl-r:reload(#{tempname})'")}", :Enter
|
||||
tmux.until { |lines| assert_equal 3, lines.item_count }
|
||||
tmux.send_keys 'C-r'
|
||||
tmux.until { |lines| assert_equal 1, lines.item_count }
|
||||
tmux.send_keys :Enter
|
||||
assert_equal 'Started', fzf_output
|
||||
wait { refute system("pgrep -f #{tempname}") }
|
||||
ensure
|
||||
system("pkill -9 -f #{tempname}")
|
||||
end
|
||||
|
||||
def test_reload
|
||||
tmux.send_keys %(seq 1000 | #{FZF} --bind 'change:reload(seq $FZF_QUERY),a:reload(seq 100),b:reload:seq 200' --header-lines 2 --multi 2), :Enter
|
||||
tmux.until { |lines| assert_equal 998, lines.match_count }
|
||||
tmux.send_keys 'a'
|
||||
tmux.until do |lines|
|
||||
assert_equal 98, lines.item_count
|
||||
assert_equal 98, lines.match_count
|
||||
end
|
||||
tmux.send_keys 'b'
|
||||
tmux.until do |lines|
|
||||
assert_equal 198, lines.item_count
|
||||
assert_equal 198, lines.match_count
|
||||
end
|
||||
tmux.send_keys :Tab
|
||||
tmux.until { |lines| assert_equal ' 198/198 (1/2)', lines[-2] }
|
||||
tmux.send_keys '555'
|
||||
tmux.until { |lines| assert_equal ' 1/553 (0/2)', lines[-2] }
|
||||
end
|
||||
|
||||
def test_reload_even_when_theres_no_match
|
||||
tmux.send_keys %(: | #{FZF} --bind 'space:reload(seq 10)'), :Enter
|
||||
tmux.until { |lines| assert_equal 0, lines.item_count }
|
||||
tmux.send_keys :Space
|
||||
tmux.until { |lines| assert_equal 10, lines.item_count }
|
||||
end
|
||||
|
||||
def test_reload_should_terminate_standard_input_stream
|
||||
tmux.send_keys %(ruby -e "STDOUT.sync = true; loop { puts 1; sleep 0.1 }" | fzf --bind 'start:reload(seq 100)'), :Enter
|
||||
tmux.until { |lines| assert_equal 100, lines.item_count }
|
||||
end
|
||||
|
||||
def test_clear_list_when_header_lines_changed_due_to_reload
|
||||
tmux.send_keys %(seq 10 | #{FZF} --header 0 --header-lines 3 --bind 'space:reload(seq 1)'), :Enter
|
||||
tmux.until { |lines| assert_includes lines, ' 9' }
|
||||
tmux.send_keys :Space
|
||||
tmux.until { |lines| refute_includes lines, ' 9' }
|
||||
end
|
||||
|
||||
def test_item_index_reset_on_reload
|
||||
tmux.send_keys "seq 10 | #{FZF} --preview 'echo [[{n}]]' --bind 'up:last,down:first,space:reload:seq 100'", :Enter
|
||||
tmux.until { |lines| assert_includes lines[1], '[[0]]' }
|
||||
tmux.send_keys :Up
|
||||
tmux.until { |lines| assert_includes lines[1], '[[9]]' }
|
||||
tmux.send_keys :Down
|
||||
tmux.until { |lines| assert_includes lines[1], '[[0]]' }
|
||||
tmux.send_keys :Space
|
||||
tmux.until do |lines|
|
||||
assert_equal 100, lines.item_count
|
||||
assert_includes lines[1], '[[0]]'
|
||||
end
|
||||
tmux.send_keys :Up
|
||||
tmux.until { |lines| assert_includes lines[1], '[[99]]' }
|
||||
end
|
||||
|
||||
def test_reload_should_update_preview
|
||||
tmux.send_keys "seq 3 | #{FZF} --bind 'ctrl-t:reload:echo 4' --preview 'echo {}' --preview-window 'nohidden'", :Enter
|
||||
tmux.until { |lines| assert_includes lines[1], '1' }
|
||||
tmux.send_keys 'C-t'
|
||||
tmux.until { |lines| assert_includes lines[1], '4' }
|
||||
end
|
||||
|
||||
def test_reload_and_change_preview_should_update_preview
|
||||
tmux.send_keys "seq 3 | #{FZF} --bind 'ctrl-t:reload(echo 4)+change-preview(echo {})'", :Enter
|
||||
tmux.until { |lines| assert_equal 3, lines.item_count }
|
||||
tmux.until { |lines| refute_includes lines[1], '1' }
|
||||
tmux.send_keys 'C-t'
|
||||
tmux.until { |lines| assert_equal 1, lines.item_count }
|
||||
tmux.until { |lines| assert_includes lines[1], '4' }
|
||||
end
|
||||
|
||||
def test_reload_sync
|
||||
tmux.send_keys "seq 100 | #{FZF} --bind 'load:reload-sync(sleep 1; seq 1000)+unbind(load)'", :Enter
|
||||
tmux.until { |lines| assert_equal 100, lines.item_count }
|
||||
tmux.send_keys '00'
|
||||
tmux.until { |lines| assert_equal 1, lines.match_count }
|
||||
# After 1 second
|
||||
tmux.until { |lines| assert_equal 10, lines.match_count }
|
||||
end
|
||||
|
||||
def test_reload_disabled_case1
|
||||
tmux.send_keys "seq 100 | #{FZF} --query 99 --bind 'space:disable-search+reload(sleep 2; seq 1000)'", :Enter
|
||||
tmux.until do |lines|
|
||||
assert_equal 100, lines.item_count
|
||||
assert_equal 1, lines.match_count
|
||||
end
|
||||
tmux.send_keys :Space
|
||||
tmux.until { |lines| assert_equal 1, lines.match_count }
|
||||
tmux.send_keys :BSpace
|
||||
tmux.until { |lines| assert_equal 0, lines.match_count }
|
||||
tmux.until { |lines| assert_equal 1000, lines.match_count }
|
||||
end
|
||||
|
||||
def test_reload_disabled_case2
|
||||
tmux.send_keys "seq 100 | #{FZF} --query 99 --bind 'space:disable-search+reload-sync(sleep 2; seq 1000)'", :Enter
|
||||
tmux.until do |lines|
|
||||
assert_equal 100, lines.item_count
|
||||
assert_equal 1, lines.match_count
|
||||
end
|
||||
tmux.send_keys :Space
|
||||
tmux.until { |lines| assert_equal 1, lines.match_count }
|
||||
tmux.send_keys :BSpace
|
||||
tmux.until { |lines| assert_equal 1, lines.match_count }
|
||||
tmux.until { |lines| assert_equal 1000, lines.match_count }
|
||||
end
|
||||
|
||||
def test_reload_disabled_case3
|
||||
tmux.send_keys "seq 100 | #{FZF} --query 99 --bind 'space:disable-search+reload(sleep 2; seq 1000)+backward-delete-char'", :Enter
|
||||
tmux.until do |lines|
|
||||
assert_equal 100, lines.item_count
|
||||
assert_equal 1, lines.match_count
|
||||
end
|
||||
tmux.send_keys :Space
|
||||
tmux.until { |lines| assert_equal 1, lines.match_count }
|
||||
tmux.send_keys :BSpace
|
||||
tmux.until { |lines| assert_equal 0, lines.match_count }
|
||||
tmux.until { |lines| assert_equal 1000, lines.match_count }
|
||||
end
|
||||
|
||||
def test_reload_disabled_case4
|
||||
tmux.send_keys "seq 100 | #{FZF} --query 99 --bind 'space:disable-search+reload-sync(sleep 2; seq 1000)+backward-delete-char'", :Enter
|
||||
tmux.until do |lines|
|
||||
assert_equal 100, lines.item_count
|
||||
assert_equal 1, lines.match_count
|
||||
end
|
||||
tmux.send_keys :Space
|
||||
tmux.until { |lines| assert_equal 1, lines.match_count }
|
||||
tmux.send_keys :BSpace
|
||||
tmux.until { |lines| assert_equal 1, lines.match_count }
|
||||
tmux.until { |lines| assert_equal 1000, lines.match_count }
|
||||
end
|
||||
|
||||
def test_reload_disabled_case5
|
||||
tmux.send_keys "seq 100 | #{FZF} --query 99 --bind 'space:disable-search+reload(echo xx; sleep 2; seq 1000)'", :Enter
|
||||
tmux.until do |lines|
|
||||
assert_equal 100, lines.item_count
|
||||
assert_equal 1, lines.match_count
|
||||
end
|
||||
tmux.send_keys :Space
|
||||
tmux.until do |lines|
|
||||
assert_equal 1, lines.item_count
|
||||
assert_equal 1, lines.match_count
|
||||
end
|
||||
tmux.send_keys :BSpace
|
||||
tmux.until { |lines| assert_equal 1001, lines.match_count }
|
||||
end
|
||||
|
||||
def test_reload_disabled_case6
|
||||
tmux.send_keys "seq 1000 | #{FZF} --disabled --bind 'change:reload:sleep 0.5; seq {q}'", :Enter
|
||||
tmux.until { |lines| assert_equal 1000, lines.match_count }
|
||||
tmux.send_keys '9'
|
||||
tmux.until { |lines| assert_equal 9, lines.match_count }
|
||||
tmux.send_keys '9'
|
||||
tmux.until { |lines| assert_equal 99, lines.match_count }
|
||||
|
||||
# TODO: How do we verify if an intermediate empty list is not shown?
|
||||
end
|
||||
|
||||
def test_reload_and_change
|
||||
tmux.send_keys "(echo foo; echo bar) | #{FZF} --bind 'load:reload-sync(sleep 60)+change-query(bar)'", :Enter
|
||||
tmux.until { |lines| assert_equal 1, lines.match_count }
|
||||
end
|
||||
|
||||
def test_become_tty
|
||||
tmux.send_keys "sleep 0.5 | #{FZF} --bind 'start:reload:ls' --bind 'load:become:tty'", :Enter
|
||||
tmux.until { |lines| assert_includes lines, '/dev/tty' }
|
||||
end
|
||||
|
||||
def test_disabled_preview_update
|
||||
tmux.send_keys "echo bar | #{FZF} --disabled --bind 'change:reload:echo foo' --preview 'echo [{q}-{}]'", :Enter
|
||||
tmux.until { |lines| assert_equal 1, lines.match_count }
|
||||
tmux.until { |lines| assert(lines.any? { |line| line.include?('[-bar]') }) }
|
||||
tmux.send_keys :x
|
||||
tmux.until { |lines| assert(lines.any? { |line| line.include?('[x-foo]') }) }
|
||||
end
|
||||
|
||||
def test_start_on_reload
|
||||
tmux.send_keys %(echo foo | #{FZF} --header Loading --header-lines 1 --bind 'start:reload:sleep 2; echo bar' --bind 'load:change-header:Loaded' --bind space:change-header:), :Enter
|
||||
tmux.until(timeout: 1) { |lines| assert_includes lines[-3], 'Loading' }
|
||||
tmux.until(timeout: 1) { |lines| refute_includes lines[-4], 'foo' }
|
||||
tmux.until { |lines| assert_includes lines[-3], 'Loaded' }
|
||||
tmux.until { |lines| assert_includes lines[-4], 'bar' }
|
||||
tmux.send_keys :Space
|
||||
tmux.until { |lines| assert_includes lines[-3], 'bar' }
|
||||
end
|
||||
|
||||
def test_become
|
||||
tmux.send_keys "seq 100 | #{FZF} --bind 'enter:become:seq {} | #{FZF}'", :Enter
|
||||
tmux.until { |lines| assert_equal 100, lines.item_count }
|
||||
tmux.send_keys 999
|
||||
tmux.until { |lines| assert_equal 0, lines.match_count }
|
||||
tmux.send_keys :Enter
|
||||
tmux.until { |lines| assert_equal 0, lines.match_count }
|
||||
tmux.send_keys :BSpace
|
||||
tmux.until { |lines| assert_equal 1, lines.match_count }
|
||||
tmux.send_keys :Enter
|
||||
tmux.until { |lines| assert_equal 99, lines.item_count }
|
||||
end
|
||||
end
|
302
test/test_filter.rb
Normal file
302
test/test_filter.rb
Normal file
@ -0,0 +1,302 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'lib/common'
|
||||
|
||||
# Non-interactive tests
|
||||
class TestFilter < TestBase
|
||||
def test_default_extended
|
||||
assert_equal '100', `seq 100 | #{FZF} -f "1 00$"`.chomp
|
||||
assert_equal '', `seq 100 | #{FZF} -f "1 00$" +x`.chomp
|
||||
end
|
||||
|
||||
def test_exact
|
||||
assert_equal 4, `seq 123 | #{FZF} -f 13`.lines.length
|
||||
assert_equal 2, `seq 123 | #{FZF} -f 13 -e`.lines.length
|
||||
assert_equal 4, `seq 123 | #{FZF} -f 13 +e`.lines.length
|
||||
end
|
||||
|
||||
def test_or_operator
|
||||
assert_equal %w[1 5 10], `seq 10 | #{FZF} -f "1 | 5"`.lines(chomp: true)
|
||||
assert_equal %w[1 10 2 3 4 5 6 7 8 9],
|
||||
`seq 10 | #{FZF} -f '1 | !1'`.lines(chomp: true)
|
||||
end
|
||||
|
||||
def test_smart_case_for_each_term
|
||||
assert_equal 1, `echo Foo bar | #{FZF} -x -f "foo Fbar" | wc -l`.to_i
|
||||
end
|
||||
|
||||
def test_filter_exitstatus
|
||||
# filter / streaming filter
|
||||
['', '--no-sort'].each do |opts|
|
||||
assert_includes `echo foo | #{FZF} -f foo #{opts}`, 'foo'
|
||||
assert_equal 0, $CHILD_STATUS.exitstatus
|
||||
|
||||
assert_empty `echo foo | #{FZF} -f bar #{opts}`
|
||||
assert_equal 1, $CHILD_STATUS.exitstatus
|
||||
end
|
||||
end
|
||||
|
||||
def test_long_line
|
||||
data = '.' * 256 * 1024
|
||||
File.open(tempname, 'w') do |f|
|
||||
f << data
|
||||
end
|
||||
assert_equal data, `#{FZF} -f . < #{tempname}`.chomp
|
||||
end
|
||||
|
||||
def test_read0
|
||||
lines = `find .`.lines(chomp: true)
|
||||
assert_equal lines.last, `find . | #{FZF} -e -f "^#{lines.last}$"`.chomp
|
||||
assert_equal \
|
||||
lines.last,
|
||||
`find . -print0 | #{FZF} --read0 -e -f "^#{lines.last}$"`.chomp
|
||||
end
|
||||
|
||||
def test_with_nth_basic
|
||||
writelines(['hello world ', 'byebye'])
|
||||
assert_equal \
|
||||
'hello world ',
|
||||
`#{FZF} -f"^he hehe" -x -n 2.. --with-nth 2,1,1 < #{tempname}`.chomp
|
||||
end
|
||||
|
||||
def test_with_nth_ansi
|
||||
writelines(["\x1b[33mhello \x1b[34;1mworld\x1b[m ", 'byebye'])
|
||||
assert_equal \
|
||||
'hello world ',
|
||||
`#{FZF} -f"^he hehe" -x -n 2.. --with-nth 2,1,1 --ansi < #{tempname}`.chomp
|
||||
end
|
||||
|
||||
def test_with_nth_no_ansi
|
||||
src = "\x1b[33mhello \x1b[34;1mworld\x1b[m "
|
||||
writelines([src, 'byebye'])
|
||||
assert_equal \
|
||||
src,
|
||||
`#{FZF} -fhehe -x -n 2.. --with-nth 2,1,1 --no-ansi < #{tempname}`.chomp
|
||||
end
|
||||
|
||||
def test_escaped_meta_characters
|
||||
input = [
|
||||
'foo^bar',
|
||||
'foo$bar',
|
||||
'foo!bar',
|
||||
"foo'bar",
|
||||
'foo bar',
|
||||
'bar foo'
|
||||
]
|
||||
writelines(input)
|
||||
|
||||
assert_equal input.length, `#{FZF} -f'foo bar' < #{tempname}`.lines.length
|
||||
assert_equal input.length - 1, `#{FZF} -f'^foo bar$' < #{tempname}`.lines.length
|
||||
assert_equal ['foo bar'], `#{FZF} -f'foo\\ bar' < #{tempname}`.lines(chomp: true)
|
||||
assert_equal ['foo bar'], `#{FZF} -f'^foo\\ bar$' < #{tempname}`.lines(chomp: true)
|
||||
assert_equal input.length - 1, `#{FZF} -f'!^foo\\ bar$' < #{tempname}`.lines.length
|
||||
end
|
||||
|
||||
def test_normalized_match
|
||||
echoes = '(echo a; echo á; echo A; echo Á;)'
|
||||
assert_equal %w[a á A Á], `#{echoes} | #{FZF} -f a`.lines.map(&:chomp)
|
||||
assert_equal %w[á Á], `#{echoes} | #{FZF} -f á`.lines.map(&:chomp)
|
||||
assert_equal %w[A Á], `#{echoes} | #{FZF} -f A`.lines.map(&:chomp)
|
||||
assert_equal %w[Á], `#{echoes} | #{FZF} -f Á`.lines.map(&:chomp)
|
||||
end
|
||||
|
||||
def test_unicode_case
|
||||
writelines(%w[строКА1 СТРОКА2 строка3 Строка4])
|
||||
assert_equal %w[СТРОКА2 Строка4], `#{FZF} -fС < #{tempname}`.lines(chomp: true)
|
||||
assert_equal %w[строКА1 СТРОКА2 строка3 Строка4], `#{FZF} -fс < #{tempname}`.lines(chomp: true)
|
||||
end
|
||||
|
||||
def test_tiebreak
|
||||
input = %w[
|
||||
--foobar--------
|
||||
-----foobar---
|
||||
----foobar--
|
||||
-------foobar-
|
||||
]
|
||||
writelines(input)
|
||||
|
||||
assert_equal input, `#{FZF} -ffoobar --tiebreak=index < #{tempname}`.lines(chomp: true)
|
||||
|
||||
by_length = %w[
|
||||
----foobar--
|
||||
-----foobar---
|
||||
-------foobar-
|
||||
--foobar--------
|
||||
]
|
||||
assert_equal by_length, `#{FZF} -ffoobar < #{tempname}`.lines(chomp: true)
|
||||
assert_equal by_length, `#{FZF} -ffoobar --tiebreak=length < #{tempname}`.lines(chomp: true)
|
||||
|
||||
by_begin = %w[
|
||||
--foobar--------
|
||||
----foobar--
|
||||
-----foobar---
|
||||
-------foobar-
|
||||
]
|
||||
assert_equal by_begin, `#{FZF} -ffoobar --tiebreak=begin < #{tempname}`.lines(chomp: true)
|
||||
assert_equal by_begin, `#{FZF} -f"!z foobar" -x --tiebreak begin < #{tempname}`.lines(chomp: true)
|
||||
|
||||
assert_equal %w[
|
||||
-------foobar-
|
||||
----foobar--
|
||||
-----foobar---
|
||||
--foobar--------
|
||||
], `#{FZF} -ffoobar --tiebreak end < #{tempname}`.lines(chomp: true)
|
||||
|
||||
assert_equal input, `#{FZF} -f"!z" -x --tiebreak end < #{tempname}`.lines(chomp: true)
|
||||
end
|
||||
|
||||
def test_tiebreak_index_begin
|
||||
writelines([
|
||||
'xoxxxxxoxx',
|
||||
'xoxxxxxox',
|
||||
'xxoxxxoxx',
|
||||
'xxxoxoxxx',
|
||||
'xxxxoxox',
|
||||
' xxoxoxxx'
|
||||
])
|
||||
|
||||
assert_equal [
|
||||
'xxxxoxox',
|
||||
' xxoxoxxx',
|
||||
'xxxoxoxxx',
|
||||
'xxoxxxoxx',
|
||||
'xoxxxxxox',
|
||||
'xoxxxxxoxx'
|
||||
], `#{FZF} -foo < #{tempname}`.lines(chomp: true)
|
||||
|
||||
assert_equal [
|
||||
'xxxoxoxxx',
|
||||
'xxxxoxox',
|
||||
' xxoxoxxx',
|
||||
'xxoxxxoxx',
|
||||
'xoxxxxxoxx',
|
||||
'xoxxxxxox'
|
||||
], `#{FZF} -foo --tiebreak=index < #{tempname}`.lines(chomp: true)
|
||||
|
||||
# Note that --tiebreak=begin is now based on the first occurrence of the
|
||||
# first character on the pattern
|
||||
assert_equal [
|
||||
' xxoxoxxx',
|
||||
'xxxoxoxxx',
|
||||
'xxxxoxox',
|
||||
'xxoxxxoxx',
|
||||
'xoxxxxxoxx',
|
||||
'xoxxxxxox'
|
||||
], `#{FZF} -foo --tiebreak=begin < #{tempname}`.lines(chomp: true)
|
||||
|
||||
assert_equal [
|
||||
' xxoxoxxx',
|
||||
'xxxoxoxxx',
|
||||
'xxxxoxox',
|
||||
'xxoxxxoxx',
|
||||
'xoxxxxxox',
|
||||
'xoxxxxxoxx'
|
||||
], `#{FZF} -foo --tiebreak=begin,length < #{tempname}`.lines(chomp: true)
|
||||
end
|
||||
|
||||
def test_tiebreak_begin_algo_v2
|
||||
writelines(['baz foo bar',
|
||||
'foo bar baz'])
|
||||
assert_equal [
|
||||
'foo bar baz',
|
||||
'baz foo bar'
|
||||
], `#{FZF} -fbar --tiebreak=begin --algo=v2 < #{tempname}`.lines(chomp: true)
|
||||
end
|
||||
|
||||
def test_tiebreak_end
|
||||
writelines(['xoxxxxxxxx',
|
||||
'xxoxxxxxxx',
|
||||
'xxxoxxxxxx',
|
||||
'xxxxoxxxx',
|
||||
'xxxxxoxxx',
|
||||
' xxxxoxxx'])
|
||||
|
||||
assert_equal [
|
||||
' xxxxoxxx',
|
||||
'xxxxoxxxx',
|
||||
'xxxxxoxxx',
|
||||
'xoxxxxxxxx',
|
||||
'xxoxxxxxxx',
|
||||
'xxxoxxxxxx'
|
||||
], `#{FZF} -fo < #{tempname}`.lines(chomp: true)
|
||||
|
||||
assert_equal [
|
||||
'xxxxxoxxx',
|
||||
' xxxxoxxx',
|
||||
'xxxxoxxxx',
|
||||
'xxxoxxxxxx',
|
||||
'xxoxxxxxxx',
|
||||
'xoxxxxxxxx'
|
||||
], `#{FZF} -fo --tiebreak=end < #{tempname}`.lines(chomp: true)
|
||||
|
||||
assert_equal [
|
||||
'xxxxxoxxx',
|
||||
' xxxxoxxx',
|
||||
'xxxxoxxxx',
|
||||
'xxxoxxxxxx',
|
||||
'xxoxxxxxxx',
|
||||
'xoxxxxxxxx'
|
||||
], `#{FZF} -fo --tiebreak=end,length,begin < #{tempname}`.lines(chomp: true)
|
||||
|
||||
writelines(['/bar/baz', '/foo/bar/baz'])
|
||||
assert_equal [
|
||||
'/foo/bar/baz',
|
||||
'/bar/baz'
|
||||
], `#{FZF} -fbaz --tiebreak=end < #{tempname}`.lines(chomp: true)
|
||||
end
|
||||
|
||||
def test_tiebreak_length_with_nth
|
||||
input = %w[
|
||||
1:hell
|
||||
123:hello
|
||||
12345:he
|
||||
1234567:h
|
||||
]
|
||||
writelines(input)
|
||||
|
||||
output = %w[
|
||||
1:hell
|
||||
12345:he
|
||||
123:hello
|
||||
1234567:h
|
||||
]
|
||||
assert_equal output, `#{FZF} -fh < #{tempname}`.lines(chomp: true)
|
||||
|
||||
# Since 0.16.8, --nth doesn't affect --tiebreak
|
||||
assert_equal output, `#{FZF} -fh -n2 -d: < #{tempname}`.lines(chomp: true)
|
||||
end
|
||||
|
||||
def test_tiebreak_chunk
|
||||
writelines(['1 foobarbaz ba',
|
||||
'2 foobar baz',
|
||||
'3 foo barbaz'])
|
||||
|
||||
assert_equal [
|
||||
'3 foo barbaz',
|
||||
'2 foobar baz',
|
||||
'1 foobarbaz ba'
|
||||
], `#{FZF} -fo --tiebreak=chunk < #{tempname}`.lines(chomp: true)
|
||||
|
||||
assert_equal [
|
||||
'1 foobarbaz ba',
|
||||
'2 foobar baz',
|
||||
'3 foo barbaz'
|
||||
], `#{FZF} -fba --tiebreak=chunk < #{tempname}`.lines(chomp: true)
|
||||
|
||||
assert_equal [
|
||||
'3 foo barbaz'
|
||||
], `#{FZF} -f'!foobar' --tiebreak=chunk < #{tempname}`.lines(chomp: true)
|
||||
end
|
||||
|
||||
def test_boundary_match
|
||||
# Underscore boundaries should be ranked lower
|
||||
{
|
||||
default: [' x '] + %w[/x/ [x] -x- -x_ _x- _x_],
|
||||
path: ['/x/', ' x '] + %w[[x] -x- -x_ _x- _x_],
|
||||
history: ['[x]', '-x-', ' x '] + %w[/x/ -x_ _x- _x_]
|
||||
}.each do |scheme, expected|
|
||||
result = `printf -- 'xxx\n-xx\nxx-\n_x_\n_x-\n-x_\n[x]\n-x-\n x \n/x/\n' | #{FZF} -f"'x'" --scheme=#{scheme}`.lines(chomp: true)
|
||||
assert_equal expected, result
|
||||
end
|
||||
end
|
||||
end
|
4504
test/test_go.rb
4504
test/test_go.rb
File diff suppressed because it is too large
Load Diff
848
test/test_layout.rb
Normal file
848
test/test_layout.rb
Normal file
@ -0,0 +1,848 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'lib/common'
|
||||
|
||||
# Test cases that mainly use assert_block to verify the layout of fzf
|
||||
class TestLayout < TestInteractive
|
||||
def assert_block(expected, lines)
|
||||
cols = expected.lines.map { it.chomp.length }.max
|
||||
top = lines.take(expected.lines.length).map { _1[0, cols].rstrip + "\n" }.join
|
||||
bottom = lines.reverse.take(expected.lines.length).reverse.map { _1[0, cols].rstrip + "\n" }.join
|
||||
assert_includes [top, bottom], expected
|
||||
end
|
||||
|
||||
def test_vanilla
|
||||
tmux.send_keys "seq 1 100000 | #{fzf}", :Enter
|
||||
block = <<~BLOCK
|
||||
2
|
||||
> 1
|
||||
100000/100000
|
||||
>
|
||||
BLOCK
|
||||
tmux.until { assert_block(block, _1) }
|
||||
|
||||
# Testing basic key bindings
|
||||
tmux.send_keys '99', 'C-a', '1', 'C-f', '3', 'C-b', 'C-h', 'C-u', 'C-e', 'C-y', 'C-k', 'Tab', 'BTab'
|
||||
block = <<~BLOCK
|
||||
> 3910
|
||||
391
|
||||
856/100000
|
||||
> 391
|
||||
BLOCK
|
||||
tmux.until { assert_block(block, _1) }
|
||||
|
||||
tmux.send_keys :Enter
|
||||
assert_equal '3910', fzf_output
|
||||
end
|
||||
|
||||
def test_header_first
|
||||
tmux.send_keys "seq 1000 | #{FZF} --header foobar --header-lines 3 --header-first", :Enter
|
||||
block = <<~OUTPUT
|
||||
> 4
|
||||
997/997
|
||||
>
|
||||
3
|
||||
2
|
||||
1
|
||||
foobar
|
||||
OUTPUT
|
||||
tmux.until { assert_block(block, _1) }
|
||||
end
|
||||
|
||||
def test_header_first_reverse
|
||||
tmux.send_keys "seq 1000 | #{FZF} --header foobar --header-lines 3 --header-first --reverse --inline-info", :Enter
|
||||
block = <<~OUTPUT
|
||||
foobar
|
||||
1
|
||||
2
|
||||
3
|
||||
> < 997/997
|
||||
> 4
|
||||
OUTPUT
|
||||
tmux.until { assert_block(block, _1) }
|
||||
end
|
||||
|
||||
def test_change_and_transform_header
|
||||
[
|
||||
'space:change-header:$(seq 4)',
|
||||
'space:transform-header:seq 4'
|
||||
].each_with_index do |binding, i|
|
||||
tmux.send_keys %(seq 3 | #{FZF} --header-lines 2 --header bar --bind "#{binding}"), :Enter
|
||||
expected = <<~OUTPUT
|
||||
> 3
|
||||
2
|
||||
1
|
||||
bar
|
||||
1/1
|
||||
>
|
||||
OUTPUT
|
||||
tmux.until { assert_block(expected, _1) }
|
||||
tmux.send_keys :Space
|
||||
expected = <<~OUTPUT
|
||||
> 3
|
||||
2
|
||||
1
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
1/1
|
||||
>
|
||||
OUTPUT
|
||||
tmux.until { assert_block(expected, _1) }
|
||||
next unless i.zero?
|
||||
|
||||
teardown
|
||||
setup
|
||||
end
|
||||
end
|
||||
|
||||
def test_change_header
|
||||
tmux.send_keys %(seq 3 | #{FZF} --header-lines 2 --header bar --bind "space:change-header:$(seq 4)"), :Enter
|
||||
expected = <<~OUTPUT
|
||||
> 3
|
||||
2
|
||||
1
|
||||
bar
|
||||
1/1
|
||||
>
|
||||
OUTPUT
|
||||
tmux.until { assert_block(expected, _1) }
|
||||
tmux.send_keys :Space
|
||||
expected = <<~OUTPUT
|
||||
> 3
|
||||
2
|
||||
1
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
1/1
|
||||
>
|
||||
OUTPUT
|
||||
tmux.until { assert_block(expected, _1) }
|
||||
end
|
||||
|
||||
def test_reload_and_change_cache
|
||||
tmux.send_keys "echo bar | #{FZF} --bind 'zero:change-header(foo)+reload(echo foo)+clear-query'", :Enter
|
||||
expected = <<~OUTPUT
|
||||
> bar
|
||||
1/1
|
||||
>
|
||||
OUTPUT
|
||||
tmux.until { assert_block(expected, _1) }
|
||||
tmux.send_keys :z
|
||||
expected = <<~OUTPUT
|
||||
> foo
|
||||
foo
|
||||
1/1
|
||||
>
|
||||
OUTPUT
|
||||
tmux.until { assert_block(expected, _1) }
|
||||
end
|
||||
|
||||
def test_toggle_header
|
||||
tmux.send_keys "seq 4 | #{FZF} --header-lines 2 --header foo --bind space:toggle-header --header-first --height 10 --border rounded", :Enter
|
||||
before = <<~OUTPUT
|
||||
╭───────
|
||||
│
|
||||
│ 4
|
||||
│ > 3
|
||||
│ 2/2
|
||||
│ >
|
||||
│ 2
|
||||
│ 1
|
||||
│ foo
|
||||
╰───────
|
||||
OUTPUT
|
||||
tmux.until { assert_block(before, _1) }
|
||||
tmux.send_keys :Space
|
||||
after = <<~OUTPUT
|
||||
╭───────
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│ 4
|
||||
│ > 3
|
||||
│ 2/2
|
||||
│ >
|
||||
╰───────
|
||||
OUTPUT
|
||||
tmux.until { assert_block(after, _1) }
|
||||
tmux.send_keys :Space
|
||||
tmux.until { assert_block(before, _1) }
|
||||
end
|
||||
|
||||
def test_height_range_fit
|
||||
tmux.send_keys 'seq 3 | fzf --height ~100% --info=inline --border rounded', :Enter
|
||||
expected = <<~OUTPUT
|
||||
╭──────────
|
||||
│ 3
|
||||
│ 2
|
||||
│ > 1
|
||||
│ > < 3/3
|
||||
╰──────────
|
||||
OUTPUT
|
||||
tmux.until { assert_block(expected, _1) }
|
||||
end
|
||||
|
||||
def test_height_range_fit_preview_above
|
||||
tmux.send_keys 'seq 3 | fzf --height ~100% --info=inline --border rounded --preview-window border-rounded --preview "seq {}" --preview-window up,60%', :Enter
|
||||
expected = <<~OUTPUT
|
||||
╭──────────
|
||||
│ ╭────────
|
||||
│ │ 1
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ ╰────────
|
||||
│ 3
|
||||
│ 2
|
||||
│ > 1
|
||||
│ > < 3/3
|
||||
╰──────────
|
||||
OUTPUT
|
||||
tmux.until { assert_block(expected, _1) }
|
||||
end
|
||||
|
||||
def test_height_range_fit_preview_above_alternative
|
||||
tmux.send_keys 'seq 3 | fzf --height ~100% --border=sharp --preview "seq {}" --preview-window up,40%,border-bottom --padding 1 --exit-0 --header hello --header-lines=2', :Enter
|
||||
expected = <<~OUTPUT
|
||||
┌─────────
|
||||
│
|
||||
│ 1
|
||||
│ 2
|
||||
│ 3
|
||||
│ ───────
|
||||
│ > 3
|
||||
│ 2
|
||||
│ 1
|
||||
│ hello
|
||||
│ 1/1 ─
|
||||
│ >
|
||||
│
|
||||
└─────────
|
||||
OUTPUT
|
||||
tmux.until { assert_block(expected, _1) }
|
||||
end
|
||||
|
||||
def test_height_range_fit_preview_left
|
||||
tmux.send_keys "seq 3 | fzf --height ~100% --border=vertical --preview 'seq {}' --preview-window left,5,border-right --padding 1 --exit-0 --header $'hello\\nworld' --header-lines=2", :Enter
|
||||
expected = <<~OUTPUT
|
||||
│
|
||||
│ 1 │ > 3
|
||||
│ 2 │ 2
|
||||
│ 3 │ 1
|
||||
│ │ hello
|
||||
│ │ world
|
||||
│ │ 1/1 ─
|
||||
│ │ >
|
||||
│
|
||||
OUTPUT
|
||||
tmux.until { assert_block(expected, _1) }
|
||||
end
|
||||
|
||||
def test_height_range_overflow
|
||||
tmux.send_keys 'seq 100 | fzf --height ~5 --info=inline --border rounded', :Enter
|
||||
expected = <<~OUTPUT
|
||||
╭──────────────
|
||||
│ 2
|
||||
│ > 1
|
||||
│ > < 100/100
|
||||
╰──────────────
|
||||
OUTPUT
|
||||
tmux.until { assert_block(expected, _1) }
|
||||
end
|
||||
|
||||
def test_no_extra_newline_issue_3209
|
||||
tmux.send_keys(%(seq 100 | #{FZF} --height 10 --preview-window up,wrap,border-rounded --preview 'printf "─%.0s" $(seq 1 "$((FZF_PREVIEW_COLUMNS - 5))"); printf $"\\e[7m%s\\e[0m" title; echo; echo something'), :Enter)
|
||||
expected = <<~OUTPUT
|
||||
╭──────────
|
||||
│ ─────────
|
||||
│ something
|
||||
│
|
||||
╰──────────
|
||||
3
|
||||
2
|
||||
> 1
|
||||
100/100 ─
|
||||
>
|
||||
OUTPUT
|
||||
tmux.until { assert_block(expected, _1) }
|
||||
end
|
||||
|
||||
def test_fzf_multi_line
|
||||
tmux.send_keys %[(echo -en '0\\0'; echo -en '1\\n2\\0'; seq 1000) | fzf --read0 --multi --bind load:select-all --border rounded], :Enter
|
||||
block = <<~BLOCK
|
||||
│ ┃998
|
||||
│ ┃999
|
||||
│ ┃1000
|
||||
│ ╹
|
||||
│ ╻1
|
||||
│ ╹2
|
||||
│ >>0
|
||||
│ 3/3 (3)
|
||||
│ >
|
||||
╰───────────
|
||||
BLOCK
|
||||
tmux.until { assert_block(block, _1) }
|
||||
tmux.send_keys :Up, :Up
|
||||
block = <<~BLOCK
|
||||
╭───────
|
||||
│ >╻1
|
||||
│ >┃2
|
||||
│ >┃3
|
||||
BLOCK
|
||||
tmux.until { assert_block(block, _1) }
|
||||
|
||||
block = <<~BLOCK
|
||||
│ >┃
|
||||
│
|
||||
│ >
|
||||
╰───
|
||||
BLOCK
|
||||
tmux.until { assert_block(block, _1) }
|
||||
end
|
||||
|
||||
def test_fzf_multi_line_reverse
|
||||
tmux.send_keys %[(echo -en '0\\0'; echo -en '1\\n2\\0'; seq 1000) | fzf --read0 --multi --bind load:select-all --border rounded --reverse], :Enter
|
||||
block = <<~BLOCK
|
||||
╭───────────
|
||||
│ >
|
||||
│ 3/3 (3)
|
||||
│ >>0
|
||||
│ ╻1
|
||||
│ ╹2
|
||||
│ ╻1
|
||||
│ ┃2
|
||||
│ ┃3
|
||||
BLOCK
|
||||
tmux.until { assert_block(block, _1) }
|
||||
end
|
||||
|
||||
def test_fzf_multi_line_no_pointer_and_marker
|
||||
tmux.send_keys %[(echo -en '0\\0'; echo -en '1\\n2\\0'; seq 1000) | fzf --read0 --multi --bind load:select-all --border rounded --reverse --pointer '' --marker '' --marker-multi-line ''], :Enter
|
||||
block = <<~BLOCK
|
||||
╭───────────
|
||||
│ >
|
||||
│ 3/3 (3)
|
||||
│ 0
|
||||
│ 1
|
||||
│ 2
|
||||
│ 1
|
||||
│ 2
|
||||
│ 3
|
||||
BLOCK
|
||||
tmux.until { assert_block(block, _1) }
|
||||
end
|
||||
|
||||
def test_gap
|
||||
tmux.send_keys %(seq 100 | #{FZF} --gap --border --reverse), :Enter
|
||||
block = <<~BLOCK
|
||||
╭─────────────────
|
||||
│ >
|
||||
│ 100/100 ──────
|
||||
│ > 1
|
||||
│ ┈┈┈┈┈┈┈┈┈┈┈┈┈┈
|
||||
│ 2
|
||||
│ ┈┈┈┈┈┈┈┈┈┈┈┈┈┈
|
||||
│ 3
|
||||
│ ┈┈┈┈┈┈┈┈┈┈┈┈┈┈
|
||||
│ 4
|
||||
BLOCK
|
||||
tmux.until { assert_block(block, _1) }
|
||||
end
|
||||
|
||||
def test_gap_2
|
||||
tmux.send_keys %(seq 100 | #{FZF} --gap=2 --gap-line xyz --border --reverse), :Enter
|
||||
block = <<~BLOCK
|
||||
╭─────────────────
|
||||
│ >
|
||||
│ 100/100 ──────
|
||||
│ > 1
|
||||
│
|
||||
│ xyzxyzxyzxyzxy
|
||||
│ 2
|
||||
│
|
||||
│ xyzxyzxyzxyzxy
|
||||
│ 3
|
||||
BLOCK
|
||||
tmux.until { assert_block(block, _1) }
|
||||
end
|
||||
|
||||
def test_list_border_and_label
|
||||
tmux.send_keys %(seq 100 | #{FZF} --border rounded --list-border double --list-label list --list-label-pos 2:bottom --header-lines 3 --query 1 --padding 1,2), :Enter
|
||||
block = <<~BLOCK
|
||||
│ ║ 11
|
||||
│ ║ > 10
|
||||
│ ║ 3
|
||||
│ ║ 2
|
||||
│ ║ 1
|
||||
│ ║ 19/97 ─
|
||||
│ ║ > 1
|
||||
│ ╚list══════
|
||||
│
|
||||
╰──────────────
|
||||
BLOCK
|
||||
tmux.until { assert_block(block, _1) }
|
||||
end
|
||||
|
||||
def test_input_border_and_label
|
||||
tmux.send_keys %(seq 100 | #{FZF} --border rounded --input-border bold --input-label input --input-label-pos 2 --header-lines 3 --query 1 --padding 1,2), :Enter
|
||||
block = <<~BLOCK
|
||||
│ 11
|
||||
│ > 10
|
||||
│ 3
|
||||
│ 2
|
||||
│ 1
|
||||
│ ┏input━━━━━
|
||||
│ ┃ 19/97
|
||||
│ ┃ > 1
|
||||
│ ┗━━━━━━━━━━
|
||||
│
|
||||
╰──────────────
|
||||
BLOCK
|
||||
tmux.until { assert_block(block, _1) }
|
||||
end
|
||||
|
||||
def test_input_border_and_label_header_first
|
||||
tmux.send_keys %(seq 100 | #{FZF} --border rounded --input-border bold --input-label input --input-label-pos 2 --header-lines 3 --query 1 --padding 1,2 --header-first), :Enter
|
||||
block = <<~BLOCK
|
||||
│ 11
|
||||
│ > 10
|
||||
│ ┏input━━━━━
|
||||
│ ┃ 19/97
|
||||
│ ┃ > 1
|
||||
│ ┗━━━━━━━━━━
|
||||
│ 3
|
||||
│ 2
|
||||
│ 1
|
||||
│
|
||||
╰──────────────
|
||||
BLOCK
|
||||
tmux.until { assert_block(block, _1) }
|
||||
end
|
||||
|
||||
def test_list_input_border_and_label
|
||||
tmux.send_keys %(
|
||||
seq 100 | #{FZF} --border rounded --list-border double --input-border bold --list-label-pos 2:bottom --input-label-pos 2 --header-lines 3 --query 1 --padding 1,2 \
|
||||
--bind 'start:transform-input-label(echo INPUT)+transform-list-label(echo LIST)' \
|
||||
--bind 'space:change-input-label( input )+change-list-label( list )'
|
||||
).strip, :Enter
|
||||
block = <<~BLOCK
|
||||
│ ║ 11
|
||||
│ ║ > 10
|
||||
│ ╚LIST══════
|
||||
│ 3
|
||||
│ 2
|
||||
│ 1
|
||||
│ ┏INPUT━━━━━
|
||||
│ ┃ 19/97
|
||||
│ ┃ > 1
|
||||
│ ┗━━━━━━━━━━
|
||||
│
|
||||
╰──────────────
|
||||
BLOCK
|
||||
tmux.until { assert_block(block, _1) }
|
||||
tmux.send_keys :Space
|
||||
block = <<~BLOCK
|
||||
│ ║ 11
|
||||
│ ║ > 10
|
||||
│ ╚ list ════
|
||||
│ 3
|
||||
│ 2
|
||||
│ 1
|
||||
│ ┏ input ━━━
|
||||
│ ┃ 19/97
|
||||
│ ┃ > 1
|
||||
│ ┗━━━━━━━━━━
|
||||
│
|
||||
╰──────────────
|
||||
BLOCK
|
||||
tmux.until { assert_block(block, _1) }
|
||||
end
|
||||
|
||||
def test_list_input_border_and_label_header_first
|
||||
tmux.send_keys %(
|
||||
seq 100 | #{FZF} --border rounded --list-border double --input-border bold --list-label-pos 2:bottom --input-label-pos 2 --header-lines 3 --query 1 --padding 1,2 \
|
||||
--bind 'start:transform-input-label(echo INPUT)+transform-list-label(echo LIST)' \
|
||||
--bind 'space:change-input-label( input )+change-list-label( list )' --header-first
|
||||
).strip, :Enter
|
||||
block = <<~BLOCK
|
||||
│ ║ 11
|
||||
│ ║ > 10
|
||||
│ ╚LIST══════
|
||||
│ ┏INPUT━━━━━
|
||||
│ ┃ 19/97
|
||||
│ ┃ > 1
|
||||
│ ┗━━━━━━━━━━
|
||||
│ 3
|
||||
│ 2
|
||||
│ 1
|
||||
│
|
||||
╰──────────────
|
||||
BLOCK
|
||||
tmux.until { assert_block(block, _1) }
|
||||
tmux.send_keys :Space
|
||||
block = <<~BLOCK
|
||||
│ ║ 11
|
||||
│ ║ > 10
|
||||
│ ╚ list ════
|
||||
│ ┏ input ━━━
|
||||
│ ┃ 19/97
|
||||
│ ┃ > 1
|
||||
│ ┗━━━━━━━━━━
|
||||
│ 3
|
||||
│ 2
|
||||
│ 1
|
||||
│
|
||||
╰──────────────
|
||||
BLOCK
|
||||
tmux.until { assert_block(block, _1) }
|
||||
end
|
||||
|
||||
def test_header_border_and_label
|
||||
tmux.send_keys %(seq 100 | #{FZF} --border rounded --header-lines 3 --header-border sharp --header-label header --header-label-pos 2:bottom --query 1 --padding 1,2), :Enter
|
||||
block = <<~BLOCK
|
||||
│ 12
|
||||
│ 11
|
||||
│ > 10
|
||||
│ ┌────────
|
||||
│ │ 3
|
||||
│ │ 2
|
||||
│ │ 1
|
||||
│ └header──
|
||||
│ 19/97 ─
|
||||
│ > 1
|
||||
│
|
||||
╰────────────
|
||||
BLOCK
|
||||
tmux.until { assert_block(block, _1) }
|
||||
end
|
||||
|
||||
def test_header_border_toggle
|
||||
tmux.send_keys %(seq 100 | #{FZF} --list-border rounded --header-border rounded --bind 'space:change-header(hello),enter:change-header()'), :Enter
|
||||
block1 = <<~BLOCK
|
||||
│ 5
|
||||
│ 4
|
||||
│ 3
|
||||
│ 2
|
||||
│ > 1
|
||||
│ 100/100 ─
|
||||
│ >
|
||||
╰────────────
|
||||
BLOCK
|
||||
tmux.until { assert_block(block1, _1) }
|
||||
|
||||
tmux.send_keys :Space
|
||||
block2 = <<~BLOCK
|
||||
│ 3
|
||||
│ 2
|
||||
│ > 1
|
||||
╰────────────
|
||||
╭────────────
|
||||
│ hello
|
||||
╰────────────
|
||||
100/100 ─
|
||||
>
|
||||
BLOCK
|
||||
tmux.until { assert_block(block2, _1) }
|
||||
|
||||
tmux.send_keys :Enter
|
||||
tmux.until { assert_block(block1, _1) }
|
||||
end
|
||||
|
||||
def test_header_border_toggle_with_header_lines
|
||||
tmux.send_keys %(seq 100 | #{FZF} --list-border rounded --header-border rounded --bind 'space:change-header(hello),enter:change-header()' --header-lines 2), :Enter
|
||||
block1 = <<~BLOCK
|
||||
│ 5
|
||||
│ 4
|
||||
│ > 3
|
||||
╰──────────
|
||||
╭──────────
|
||||
│ 2
|
||||
│ 1
|
||||
╰──────────
|
||||
98/98 ─
|
||||
>
|
||||
BLOCK
|
||||
tmux.until { assert_block(block1, _1) }
|
||||
|
||||
tmux.send_keys :Space
|
||||
block2 = <<~BLOCK
|
||||
│ 4
|
||||
│ > 3
|
||||
╰──────────
|
||||
╭──────────
|
||||
│ 2
|
||||
│ 1
|
||||
│ hello
|
||||
╰──────────
|
||||
98/98 ─
|
||||
>
|
||||
BLOCK
|
||||
tmux.until { assert_block(block2, _1) }
|
||||
|
||||
tmux.send_keys :Enter
|
||||
tmux.until { assert_block(block1, _1) }
|
||||
end
|
||||
|
||||
def test_header_border_toggle_with_header_lines_header_first
|
||||
tmux.send_keys %(seq 100 | #{FZF} --list-border rounded --header-border rounded --bind 'space:change-header(hello),enter:change-header()' --header-lines 2 --header-first), :Enter
|
||||
block1 = <<~BLOCK
|
||||
│ 5
|
||||
│ 4
|
||||
│ > 3
|
||||
╰──────────
|
||||
98/98 ─
|
||||
>
|
||||
╭──────────
|
||||
│ 2
|
||||
│ 1
|
||||
╰──────────
|
||||
BLOCK
|
||||
tmux.until { assert_block(block1, _1) }
|
||||
|
||||
tmux.send_keys :Space
|
||||
block2 = <<~BLOCK
|
||||
│ 4
|
||||
│ > 3
|
||||
╰──────────
|
||||
98/98 ─
|
||||
>
|
||||
╭──────────
|
||||
│ 2
|
||||
│ 1
|
||||
│ hello
|
||||
╰──────────
|
||||
BLOCK
|
||||
tmux.until { assert_block(block2, _1) }
|
||||
|
||||
tmux.send_keys :Enter
|
||||
tmux.until { assert_block(block1, _1) }
|
||||
end
|
||||
|
||||
def test_header_border_toggle_with_header_lines_header_lines_border
|
||||
tmux.send_keys %(seq 100 | #{FZF} --list-border rounded --header-border rounded --bind 'space:change-header(hello),enter:change-header()' --header-lines 2 --header-lines-border double), :Enter
|
||||
block1 = <<~BLOCK
|
||||
│ 5
|
||||
│ 4
|
||||
│ > 3
|
||||
╰──────────
|
||||
╔══════════
|
||||
║ 2
|
||||
║ 1
|
||||
╚══════════
|
||||
98/98 ─
|
||||
>
|
||||
BLOCK
|
||||
tmux.until { assert_block(block1, _1) }
|
||||
|
||||
tmux.send_keys :Space
|
||||
block2 = <<~BLOCK
|
||||
│ > 3
|
||||
╰──────────
|
||||
╔══════════
|
||||
║ 2
|
||||
║ 1
|
||||
╚══════════
|
||||
╭──────────
|
||||
│ hello
|
||||
╰──────────
|
||||
98/98 ─
|
||||
>
|
||||
BLOCK
|
||||
tmux.until { assert_block(block2, _1) }
|
||||
|
||||
tmux.send_keys :Enter
|
||||
tmux.until { assert_block(block1, _1) }
|
||||
end
|
||||
|
||||
def test_header_border_toggle_with_header_lines_header_first_header_lines_border
|
||||
tmux.send_keys %(seq 100 | #{FZF} --list-border rounded --header-border rounded --bind 'space:change-header(hello),enter:change-header()' --header-lines 2 --header-first --header-lines-border double), :Enter
|
||||
block1 = <<~BLOCK
|
||||
│ 5
|
||||
│ 4
|
||||
│ > 3
|
||||
╰──────────
|
||||
╔══════════
|
||||
║ 2
|
||||
║ 1
|
||||
╚══════════
|
||||
98/98 ─
|
||||
>
|
||||
BLOCK
|
||||
tmux.until { assert_block(block1, _1) }
|
||||
|
||||
tmux.send_keys :Space
|
||||
block2 = <<~BLOCK
|
||||
│ > 3
|
||||
╰──────────
|
||||
╔══════════
|
||||
║ 2
|
||||
║ 1
|
||||
╚══════════
|
||||
98/98 ─
|
||||
>
|
||||
╭──────────
|
||||
│ hello
|
||||
╰──────────
|
||||
BLOCK
|
||||
tmux.until { assert_block(block2, _1) }
|
||||
|
||||
tmux.send_keys :Enter
|
||||
tmux.until { assert_block(block1, _1) }
|
||||
end
|
||||
|
||||
def test_header_border_and_label_header_first
|
||||
tmux.send_keys %(seq 100 | #{FZF} --border rounded --header-lines 3 --header-border sharp --header-label header --header-label-pos 2:bottom --query 1 --padding 1,2 --header-first), :Enter
|
||||
block = <<~BLOCK
|
||||
│ 12
|
||||
│ 11
|
||||
│ > 10
|
||||
│ 19/97 ─
|
||||
│ > 1
|
||||
│ ┌────────
|
||||
│ │ 3
|
||||
│ │ 2
|
||||
│ │ 1
|
||||
│ └header──
|
||||
│
|
||||
╰────────────
|
||||
BLOCK
|
||||
tmux.until { assert_block(block, _1) }
|
||||
end
|
||||
|
||||
def test_header_border_and_label_with_list_border
|
||||
tmux.send_keys %(seq 100 | #{FZF} --border rounded --list-border double --list-label list --list-label-pos 2:bottom --header-lines 3 --header-border sharp --header-label header --header-label-pos 2:bottom --query 1 --padding 1,2), :Enter
|
||||
block = <<~BLOCK
|
||||
│ ║ 12
|
||||
│ ║ 11
|
||||
│ ║ > 10
|
||||
│ ╚list══════
|
||||
│ ┌──────────
|
||||
│ │ 3
|
||||
│ │ 2
|
||||
│ │ 1
|
||||
│ └header────
|
||||
│ 19/97 ─
|
||||
│ > 1
|
||||
│
|
||||
╰──────────────
|
||||
BLOCK
|
||||
tmux.until { assert_block(block, _1) }
|
||||
end
|
||||
|
||||
def test_header_border_and_label_with_list_border_header_first
|
||||
tmux.send_keys %(seq 100 | #{FZF} --border rounded --list-border double --list-label list --list-label-pos 2:bottom --header-lines 3 --header-border sharp --header-label header --header-label-pos 2:bottom --query 1 --padding 1,2 --header-first), :Enter
|
||||
block = <<~BLOCK
|
||||
│ ║ 12
|
||||
│ ║ 11
|
||||
│ ║ > 10
|
||||
│ ╚list══════
|
||||
│ 19/97 ─
|
||||
│ > 1
|
||||
│ ┌──────────
|
||||
│ │ 3
|
||||
│ │ 2
|
||||
│ │ 1
|
||||
│ └header────
|
||||
│
|
||||
╰──────────────
|
||||
BLOCK
|
||||
tmux.until { assert_block(block, _1) }
|
||||
end
|
||||
|
||||
def test_all_borders
|
||||
tmux.send_keys %(seq 100 | #{FZF} --border rounded --list-border double --list-label list --list-label-pos 2:bottom --header-lines 3 --header-border sharp --header-label header --header-label-pos 2:bottom --query 1 --padding 1,2 --input-border bold --input-label input --input-label-pos 2:bottom), :Enter
|
||||
block = <<~BLOCK
|
||||
│ ║ 12
|
||||
│ ║ 11
|
||||
│ ║ > 10
|
||||
│ ╚list══════
|
||||
│ ┌──────────
|
||||
│ │ 3
|
||||
│ │ 2
|
||||
│ │ 1
|
||||
│ └header────
|
||||
│ ┏━━━━━━━━━━
|
||||
│ ┃ 19/97
|
||||
│ ┃ > 1
|
||||
│ ┗input━━━━━
|
||||
│
|
||||
╰──────────────
|
||||
BLOCK
|
||||
tmux.until { assert_block(block, _1) }
|
||||
end
|
||||
|
||||
def test_all_borders_header_first
|
||||
tmux.send_keys %(seq 100 | #{FZF} --border rounded --list-border double --list-label list --list-label-pos 2:bottom --header-lines 3 --header-border sharp --header-label header --header-label-pos 2:bottom --query 1 --padding 1,2 --input-border bold --input-label input --input-label-pos 2:bottom --header-first), :Enter
|
||||
block = <<~BLOCK
|
||||
│ ║ 12
|
||||
│ ║ 11
|
||||
│ ║ > 10
|
||||
│ ╚list══════
|
||||
│ ┏━━━━━━━━━━
|
||||
│ ┃ 19/97
|
||||
│ ┃ > 1
|
||||
│ ┗input━━━━━
|
||||
│ ┌──────────
|
||||
│ │ 3
|
||||
│ │ 2
|
||||
│ │ 1
|
||||
│ └header────
|
||||
│
|
||||
╰──────────────
|
||||
BLOCK
|
||||
tmux.until { assert_block(block, _1) }
|
||||
end
|
||||
|
||||
def test_style_full_adaptive_height
|
||||
tmux.send_keys %(seq 1| #{FZF} --style=full --height=~100% --header-lines=1 --info=default), :Enter
|
||||
block = <<~BLOCK
|
||||
╭────────
|
||||
╰────────
|
||||
╭────────
|
||||
│ 1
|
||||
╰────────
|
||||
╭────────
|
||||
│ 0/0
|
||||
│ >
|
||||
╰────────
|
||||
BLOCK
|
||||
tmux.until { assert_block(block, _1) }
|
||||
end
|
||||
|
||||
def test_style_full_adaptive_height_double
|
||||
tmux.send_keys %(seq 1| #{FZF} --style=full:double --border --height=~100% --header-lines=1 --info=default), :Enter
|
||||
block = <<~BLOCK
|
||||
╔══════════
|
||||
║ ╔════════
|
||||
║ ╚════════
|
||||
║ ╔════════
|
||||
║ ║ 1
|
||||
║ ╚════════
|
||||
║ ╔════════
|
||||
║ ║ 0/0
|
||||
║ ║ >
|
||||
║ ╚════════
|
||||
╚══════════
|
||||
BLOCK
|
||||
tmux.until { assert_block(block, _1) }
|
||||
end
|
||||
|
||||
def test_preview_window_noinfo
|
||||
# │ 1 ││
|
||||
tmux.send_keys %(#{FZF} --preview 'seq 1000' --preview-window top,noinfo --scrollbar --bind space:change-preview-window:info), :Enter
|
||||
tmux.until do |lines|
|
||||
assert lines[1]&.start_with?('│ 1')
|
||||
assert lines[1]&.end_with?(' ││')
|
||||
end
|
||||
tmux.send_keys :Space
|
||||
tmux.until do |lines|
|
||||
assert lines[1]&.start_with?('│ 1')
|
||||
assert lines[1]&.end_with?('1000││')
|
||||
end
|
||||
end
|
||||
end
|
545
test/test_preview.rb
Normal file
545
test/test_preview.rb
Normal file
@ -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
|
52
test/test_server.rb
Normal file
52
test/test_server.rb
Normal file
@ -0,0 +1,52 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'lib/common'
|
||||
|
||||
# Test cases for API server
|
||||
class TestServer < TestInteractive
|
||||
def test_listen
|
||||
{ '--listen 6266' => -> { URI('http://localhost:6266') },
|
||||
"--listen --sync --bind 'start:execute-silent:echo $FZF_PORT > /tmp/fzf-port'" =>
|
||||
-> { URI("http://localhost:#{File.read('/tmp/fzf-port').chomp}") } }.each do |opts, fn|
|
||||
tmux.send_keys "seq 10 | fzf #{opts}", :Enter
|
||||
tmux.until { |lines| assert_equal 10, lines.item_count }
|
||||
state = JSON.parse(Net::HTTP.get(fn.call), symbolize_names: true)
|
||||
assert_equal 10, state[:totalCount]
|
||||
assert_equal 10, state[:matchCount]
|
||||
assert_empty state[:query]
|
||||
assert_equal({ index: 0, text: '1' }, state[:current])
|
||||
|
||||
Net::HTTP.post(fn.call, 'change-query(yo)+reload(seq 100)+change-prompt:hundred> ')
|
||||
tmux.until { |lines| assert_equal 100, lines.item_count }
|
||||
tmux.until { |lines| assert_equal 'hundred> yo', lines[-1] }
|
||||
state = JSON.parse(Net::HTTP.get(fn.call), symbolize_names: true)
|
||||
assert_equal 100, state[:totalCount]
|
||||
assert_equal 0, state[:matchCount]
|
||||
assert_equal 'yo', state[:query]
|
||||
assert_nil state[:current]
|
||||
|
||||
teardown
|
||||
setup
|
||||
end
|
||||
end
|
||||
|
||||
def test_listen_with_api_key
|
||||
post_uri = URI('http://localhost:6266')
|
||||
tmux.send_keys 'seq 10 | FZF_API_KEY=123abc fzf --listen 6266', :Enter
|
||||
tmux.until { |lines| assert_equal 10, lines.item_count }
|
||||
# Incorrect API Key
|
||||
[nil, { 'x-api-key' => '' }, { 'x-api-key' => '124abc' }].each do |headers|
|
||||
res = Net::HTTP.post(post_uri, 'change-query(yo)+reload(seq 100)+change-prompt:hundred> ', headers)
|
||||
assert_equal '401', res.code
|
||||
assert_equal 'Unauthorized', res.message
|
||||
assert_equal "invalid api key\n", res.body
|
||||
end
|
||||
# Valid API Key
|
||||
[{ 'x-api-key' => '123abc' }, { 'X-API-Key' => '123abc' }].each do |headers|
|
||||
res = Net::HTTP.post(post_uri, 'change-query(yo)+reload(seq 100)+change-prompt:hundred> ', headers)
|
||||
assert_equal '200', res.code
|
||||
tmux.until { |lines| assert_equal 100, lines.item_count }
|
||||
tmux.until { |lines| assert_equal 'hundred> yo', lines[-1] }
|
||||
end
|
||||
end
|
||||
end
|
485
test/test_shell_integration.rb
Normal file
485
test/test_shell_integration.rb
Normal file
@ -0,0 +1,485 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'lib/common'
|
||||
|
||||
# Testing shell integration
|
||||
module TestShell
|
||||
attr_reader :tmux
|
||||
|
||||
def setup
|
||||
@tmux = Tmux.new(shell)
|
||||
tmux.prepare
|
||||
end
|
||||
|
||||
def teardown
|
||||
@tmux.kill
|
||||
end
|
||||
|
||||
def set_var(name, val)
|
||||
tmux.prepare
|
||||
tmux.send_keys "export #{name}='#{val}'", :Enter
|
||||
tmux.prepare
|
||||
end
|
||||
|
||||
def unset_var(name)
|
||||
tmux.prepare
|
||||
tmux.send_keys "unset #{name}", :Enter
|
||||
tmux.prepare
|
||||
end
|
||||
|
||||
def test_ctrl_t
|
||||
set_var('FZF_CTRL_T_COMMAND', 'seq 100')
|
||||
|
||||
tmux.prepare
|
||||
tmux.send_keys 'C-t'
|
||||
tmux.until { |lines| assert_equal 100, lines.item_count }
|
||||
tmux.send_keys :Tab, :Tab, :Tab
|
||||
tmux.until { |lines| assert lines.any_include?(' (3)') }
|
||||
tmux.send_keys :Enter
|
||||
tmux.until { |lines| assert lines.any_include?('1 2 3') }
|
||||
tmux.send_keys 'C-c'
|
||||
end
|
||||
|
||||
def test_ctrl_t_unicode
|
||||
writelines(['fzf-unicode 테스트1', 'fzf-unicode 테스트2'])
|
||||
set_var('FZF_CTRL_T_COMMAND', "cat #{tempname}")
|
||||
|
||||
tmux.prepare
|
||||
tmux.send_keys 'echo ', 'C-t'
|
||||
tmux.until { |lines| assert_equal 2, lines.item_count }
|
||||
tmux.send_keys 'fzf-unicode'
|
||||
tmux.until { |lines| assert_equal 2, lines.match_count }
|
||||
|
||||
tmux.send_keys '1'
|
||||
tmux.until { |lines| assert_equal 1, lines.match_count }
|
||||
tmux.send_keys :Tab
|
||||
tmux.until { |lines| assert_equal 1, lines.select_count }
|
||||
|
||||
tmux.send_keys :BSpace
|
||||
tmux.until { |lines| assert_equal 2, lines.match_count }
|
||||
|
||||
tmux.send_keys '2'
|
||||
tmux.until { |lines| assert_equal 1, lines.match_count }
|
||||
tmux.send_keys :Tab
|
||||
tmux.until { |lines| assert_equal 2, lines.select_count }
|
||||
|
||||
tmux.send_keys :Enter
|
||||
tmux.until { |lines| assert_match(/echo .*fzf-unicode.*1.* .*fzf-unicode.*2/, lines.join) }
|
||||
tmux.send_keys :Enter
|
||||
tmux.until { |lines| assert_equal 'fzf-unicode 테스트1 fzf-unicode 테스트2', lines[-1] }
|
||||
end
|
||||
|
||||
def test_alt_c
|
||||
tmux.prepare
|
||||
tmux.send_keys :Escape, :c
|
||||
lines = tmux.until { |lines| assert_operator lines.match_count, :>, 0 }
|
||||
expected = lines.reverse.find { |l| l.start_with?('> ') }[2..]
|
||||
tmux.send_keys :Enter
|
||||
tmux.prepare
|
||||
tmux.send_keys :pwd, :Enter
|
||||
tmux.until { |lines| assert lines[-1]&.end_with?(expected) }
|
||||
end
|
||||
|
||||
def test_alt_c_command
|
||||
set_var('FZF_ALT_C_COMMAND', 'echo /tmp')
|
||||
|
||||
tmux.prepare
|
||||
tmux.send_keys 'cd /', :Enter
|
||||
|
||||
tmux.prepare
|
||||
tmux.send_keys :Escape, :c
|
||||
tmux.until { |lines| assert_equal 1, lines.item_count }
|
||||
tmux.send_keys :Enter
|
||||
|
||||
tmux.prepare
|
||||
tmux.send_keys :pwd, :Enter
|
||||
tmux.until { |lines| assert_equal '/tmp', lines[-1] }
|
||||
end
|
||||
|
||||
def test_ctrl_r
|
||||
tmux.prepare
|
||||
tmux.send_keys 'echo 1st', :Enter
|
||||
tmux.prepare
|
||||
tmux.send_keys 'echo 2nd', :Enter
|
||||
tmux.prepare
|
||||
tmux.send_keys 'echo 3d', :Enter
|
||||
tmux.prepare
|
||||
3.times do
|
||||
tmux.send_keys 'echo 3rd', :Enter
|
||||
tmux.prepare
|
||||
end
|
||||
tmux.send_keys 'echo 4th', :Enter
|
||||
tmux.prepare
|
||||
tmux.send_keys 'C-r'
|
||||
tmux.until { |lines| assert_operator lines.match_count, :>, 0 }
|
||||
tmux.send_keys 'e3d'
|
||||
# Duplicates removed: 3d (1) + 3rd (1) => 2 matches
|
||||
tmux.until { |lines| assert_equal 2, lines.match_count }
|
||||
tmux.until { |lines| assert lines[-3]&.end_with?(' echo 3d') }
|
||||
tmux.send_keys 'C-r'
|
||||
tmux.until { |lines| assert lines[-3]&.end_with?(' echo 3rd') }
|
||||
tmux.send_keys :Enter
|
||||
tmux.until { |lines| assert_equal 'echo 3rd', lines[-1] }
|
||||
tmux.send_keys :Enter
|
||||
tmux.until { |lines| assert_equal '3rd', lines[-1] }
|
||||
end
|
||||
|
||||
def test_ctrl_r_multiline
|
||||
# NOTE: Current bash implementation shows an extra new line if there's
|
||||
# only entry in the history
|
||||
tmux.send_keys ':', :Enter
|
||||
tmux.send_keys 'echo "foo', :Enter, 'bar"', :Enter
|
||||
tmux.until { |lines| assert_equal %w[foo bar], lines[-2..] }
|
||||
tmux.prepare
|
||||
tmux.send_keys 'C-r'
|
||||
tmux.until { |lines| assert_equal '>', lines[-1] }
|
||||
tmux.send_keys 'foo bar'
|
||||
tmux.until { |lines| assert_includes lines[-4], '"foo' } unless shell == :zsh
|
||||
tmux.until { |lines| assert lines[-3]&.match?(/bar"␊?/) }
|
||||
tmux.send_keys :Enter
|
||||
tmux.until { |lines| assert lines[-1]&.match?(/bar"␊?/) }
|
||||
tmux.send_keys :Enter
|
||||
tmux.until { |lines| assert_equal %w[foo bar], lines[-2..] }
|
||||
end
|
||||
|
||||
def test_ctrl_r_abort
|
||||
skip("doesn't restore the original line when search is aborted pre Bash 4") if shell == :bash && `#{Shell.bash} --version`[/(?<= version )\d+/].to_i < 4
|
||||
%w[foo ' "].each do |query|
|
||||
tmux.prepare
|
||||
tmux.send_keys :Enter, query
|
||||
tmux.until { |lines| assert lines[-1]&.start_with?(query) }
|
||||
tmux.send_keys 'C-r'
|
||||
tmux.until { |lines| assert_equal "> #{query}", lines[-1] }
|
||||
tmux.send_keys 'C-g'
|
||||
tmux.until { |lines| assert lines[-1]&.start_with?(query) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module CompletionTest
|
||||
def test_file_completion
|
||||
FileUtils.mkdir_p('/tmp/fzf-test')
|
||||
FileUtils.mkdir_p('/tmp/fzf test')
|
||||
(1..100).each { |i| FileUtils.touch("/tmp/fzf-test/#{i}") }
|
||||
['no~such~user', '/tmp/fzf test/foobar'].each do |f|
|
||||
FileUtils.touch(File.expand_path(f))
|
||||
end
|
||||
tmux.prepare
|
||||
tmux.send_keys 'cat /tmp/fzf-test/10**', :Tab
|
||||
tmux.until { |lines| assert_operator lines.match_count, :>, 0 }
|
||||
tmux.send_keys ' !d'
|
||||
tmux.until { |lines| assert_equal 2, lines.match_count }
|
||||
tmux.send_keys :Tab, :Tab
|
||||
tmux.until { |lines| assert_equal 2, lines.select_count }
|
||||
tmux.send_keys :Enter
|
||||
tmux.until(true) do |lines|
|
||||
assert_equal 'cat /tmp/fzf-test/10 /tmp/fzf-test/100', lines[-1]
|
||||
end
|
||||
|
||||
# ~USERNAME**<TAB>
|
||||
user = `whoami`.chomp
|
||||
tmux.send_keys 'C-u'
|
||||
tmux.send_keys "cat ~#{user}**", :Tab
|
||||
tmux.until { |lines| assert_operator lines.match_count, :>, 0 }
|
||||
tmux.send_keys "/#{user}"
|
||||
tmux.until { |lines| assert(lines.any? { |l| l.end_with?("/#{user}") }) }
|
||||
tmux.send_keys :Enter
|
||||
tmux.until(true) do |lines|
|
||||
assert_match %r{cat .*/#{user}}, lines[-1]
|
||||
end
|
||||
|
||||
# ~INVALID_USERNAME**<TAB>
|
||||
tmux.send_keys 'C-u'
|
||||
tmux.send_keys 'cat ~such**', :Tab
|
||||
tmux.until(true) { |lines| assert lines.any_include?('no~such~user') }
|
||||
tmux.send_keys :Enter
|
||||
tmux.until(true) { |lines| assert_equal 'cat no~such~user', lines[-1] }
|
||||
|
||||
# /tmp/fzf\ test**<TAB>
|
||||
tmux.send_keys 'C-u'
|
||||
tmux.send_keys 'cat /tmp/fzf\ test/**', :Tab
|
||||
tmux.until { |lines| assert_operator lines.match_count, :>, 0 }
|
||||
tmux.send_keys 'foobar$'
|
||||
tmux.until do |lines|
|
||||
assert_equal 1, lines.match_count
|
||||
assert lines.any_include?('> /tmp/fzf test/foobar')
|
||||
end
|
||||
tmux.send_keys :Enter
|
||||
tmux.until(true) { |lines| assert_equal 'cat /tmp/fzf\ test/foobar', lines[-1] }
|
||||
|
||||
# Should include hidden files
|
||||
(1..100).each { |i| FileUtils.touch("/tmp/fzf-test/.hidden-#{i}") }
|
||||
tmux.send_keys 'C-u'
|
||||
tmux.send_keys 'cat /tmp/fzf-test/hidden**', :Tab
|
||||
tmux.until(true) do |lines|
|
||||
assert_equal 100, lines.match_count
|
||||
assert lines.any_include?('/tmp/fzf-test/.hidden-')
|
||||
end
|
||||
tmux.send_keys :Enter
|
||||
ensure
|
||||
['/tmp/fzf-test', '/tmp/fzf test', '~/.fzf-home', 'no~such~user'].each do |f|
|
||||
FileUtils.rm_rf(File.expand_path(f))
|
||||
end
|
||||
end
|
||||
|
||||
def test_file_completion_root
|
||||
tmux.send_keys 'ls /**', :Tab
|
||||
tmux.until { |lines| assert_operator lines.match_count, :>, 0 }
|
||||
tmux.send_keys :Enter
|
||||
end
|
||||
|
||||
def test_dir_completion
|
||||
(1..100).each do |idx|
|
||||
FileUtils.mkdir_p("/tmp/fzf-test/d#{idx}")
|
||||
end
|
||||
FileUtils.touch('/tmp/fzf-test/d55/xxx')
|
||||
tmux.prepare
|
||||
tmux.send_keys 'cd /tmp/fzf-test/**', :Tab
|
||||
tmux.until { |lines| assert_operator lines.match_count, :>, 0 }
|
||||
tmux.send_keys :Tab, :Tab # Tab does not work here
|
||||
tmux.send_keys 55
|
||||
tmux.until do |lines|
|
||||
assert_equal 1, lines.match_count
|
||||
assert_includes lines, '> 55'
|
||||
assert_includes lines, '> /tmp/fzf-test/d55'
|
||||
end
|
||||
tmux.send_keys :Enter
|
||||
tmux.until(true) { |lines| assert_equal 'cd /tmp/fzf-test/d55/', lines[-1] }
|
||||
tmux.send_keys :xx
|
||||
tmux.until { |lines| assert_equal 'cd /tmp/fzf-test/d55/xx', lines[-1] }
|
||||
|
||||
# Should not match regular files (bash-only)
|
||||
if instance_of?(TestBash)
|
||||
tmux.send_keys :Tab
|
||||
tmux.until { |lines| assert_equal 'cd /tmp/fzf-test/d55/xx', lines[-1] }
|
||||
end
|
||||
|
||||
# Fail back to plusdirs
|
||||
tmux.send_keys :BSpace, :BSpace, :BSpace
|
||||
tmux.until { |lines| assert_equal 'cd /tmp/fzf-test/d55', lines[-1] }
|
||||
tmux.send_keys :Tab
|
||||
tmux.until { |lines| assert_equal 'cd /tmp/fzf-test/d55/', lines[-1] }
|
||||
end
|
||||
|
||||
def test_process_completion
|
||||
tmux.send_keys 'sleep 12345 &', :Enter
|
||||
lines = tmux.until { |lines| assert lines[-1]&.start_with?('[1] ') }
|
||||
pid = lines[-1]&.split&.last
|
||||
tmux.prepare
|
||||
tmux.send_keys 'C-L'
|
||||
tmux.send_keys 'kill **', :Tab
|
||||
tmux.until { |lines| assert_operator lines.match_count, :>, 0 }
|
||||
tmux.send_keys 'sleep12345'
|
||||
tmux.until { |lines| assert lines.any_include?('sleep 12345') }
|
||||
tmux.send_keys :Enter
|
||||
tmux.until(true) { |lines| assert_equal "kill #{pid}", lines[-1] }
|
||||
ensure
|
||||
if pid
|
||||
begin
|
||||
Process.kill('KILL', pid.to_i)
|
||||
rescue StandardError
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_custom_completion
|
||||
tmux.send_keys '_fzf_compgen_path() { echo "$1"; seq 10; }', :Enter
|
||||
tmux.prepare
|
||||
tmux.send_keys 'ls /tmp/**', :Tab
|
||||
tmux.until { |lines| assert_equal 11, lines.match_count }
|
||||
tmux.send_keys :Tab, :Tab, :Tab
|
||||
tmux.until { |lines| assert_equal 3, lines.select_count }
|
||||
tmux.send_keys :Enter
|
||||
tmux.until(true) { |lines| assert_equal 'ls /tmp 1 2', lines[-1] }
|
||||
end
|
||||
|
||||
def test_unset_completion
|
||||
tmux.send_keys 'export FZFFOOBAR=BAZ', :Enter
|
||||
tmux.prepare
|
||||
|
||||
# Using tmux
|
||||
tmux.send_keys 'unset FZFFOOBR**', :Tab
|
||||
tmux.until { |lines| assert_equal 1, lines.match_count }
|
||||
tmux.send_keys :Enter
|
||||
tmux.until { |lines| assert_equal 'unset FZFFOOBAR', lines[-1] }
|
||||
tmux.send_keys 'C-c'
|
||||
|
||||
# FZF_TMUX=1
|
||||
new_shell
|
||||
tmux.focus
|
||||
tmux.send_keys 'unset FZFFOOBR**', :Tab
|
||||
tmux.until { |lines| assert_equal 1, lines.match_count }
|
||||
tmux.send_keys :Enter
|
||||
tmux.until { |lines| assert_equal 'unset FZFFOOBAR', lines[-1] }
|
||||
end
|
||||
|
||||
def test_completion_in_command_sequence
|
||||
tmux.send_keys 'export FZFFOOBAR=BAZ', :Enter
|
||||
tmux.prepare
|
||||
|
||||
triggers = ['**', '~~', '++', 'ff', '/']
|
||||
triggers.push('&', '[', ';', '`') if instance_of?(TestZsh)
|
||||
|
||||
triggers.each do |trigger|
|
||||
set_var('FZF_COMPLETION_TRIGGER', trigger)
|
||||
command = "echo foo; QUX=THUD unset FZFFOOBR#{trigger}"
|
||||
tmux.send_keys command.sub(/(;|`)$/, '\\\\\1'), :Tab
|
||||
tmux.until { |lines| assert_equal 1, lines.match_count }
|
||||
tmux.send_keys :Enter
|
||||
tmux.until { |lines| assert_equal 'echo foo; QUX=THUD unset FZFFOOBAR', lines[-1] }
|
||||
end
|
||||
end
|
||||
|
||||
def test_file_completion_unicode
|
||||
FileUtils.mkdir_p('/tmp/fzf-test')
|
||||
tmux.paste "cd /tmp/fzf-test; echo test3 > $'fzf-unicode \\355\\205\\214\\354\\212\\244\\355\\212\\2701'; echo test4 > $'fzf-unicode \\355\\205\\214\\354\\212\\244\\355\\212\\2702'"
|
||||
tmux.prepare
|
||||
tmux.send_keys 'cat fzf-unicode**', :Tab
|
||||
tmux.until { |lines| assert_equal 2, lines.match_count }
|
||||
|
||||
tmux.send_keys '1'
|
||||
tmux.until { |lines| assert_equal 1, lines.match_count }
|
||||
tmux.send_keys :Tab
|
||||
tmux.until { |lines| assert_equal 1, lines.select_count }
|
||||
|
||||
tmux.send_keys :BSpace
|
||||
tmux.until { |lines| assert_equal 2, lines.match_count }
|
||||
|
||||
tmux.send_keys '2'
|
||||
tmux.until { |lines| assert_equal 1, lines.select_count }
|
||||
tmux.send_keys :Tab
|
||||
tmux.until { |lines| assert_equal 2, lines.select_count }
|
||||
|
||||
tmux.send_keys :Enter
|
||||
tmux.until(true) { |lines| assert_match(/cat .*fzf-unicode.*1.* .*fzf-unicode.*2/, lines[-1]) }
|
||||
tmux.send_keys :Enter
|
||||
tmux.until { |lines| assert_equal %w[test3 test4], lines[-2..] }
|
||||
end
|
||||
|
||||
def test_custom_completion_api
|
||||
tmux.send_keys 'eval "_fzf$(declare -f _comprun)"', :Enter
|
||||
%w[f g].each do |command|
|
||||
tmux.prepare
|
||||
tmux.send_keys "#{command} b**", :Tab
|
||||
tmux.until do |lines|
|
||||
assert_equal 2, lines.item_count
|
||||
assert_equal 1, lines.match_count
|
||||
assert lines.any_include?("prompt-#{command}")
|
||||
assert lines.any_include?("preview-#{command}-bar")
|
||||
end
|
||||
tmux.send_keys :Enter
|
||||
tmux.until { |lines| assert_equal "#{command} #{command}barbar", lines[-1] }
|
||||
tmux.send_keys 'C-u'
|
||||
end
|
||||
ensure
|
||||
tmux.prepare
|
||||
tmux.send_keys 'unset -f _fzf_comprun', :Enter
|
||||
end
|
||||
|
||||
def test_ssh_completion
|
||||
(1..5).each { |i| FileUtils.touch("/tmp/fzf-test-ssh-#{i}") }
|
||||
|
||||
tmux.send_keys 'ssh jg@localhost**', :Tab
|
||||
tmux.until do |lines|
|
||||
assert_operator lines.match_count, :>=, 1
|
||||
end
|
||||
|
||||
tmux.send_keys :Enter
|
||||
tmux.until { |lines| assert lines.any_include?('ssh jg@localhost') }
|
||||
tmux.send_keys ' -i /tmp/fzf-test-ssh**', :Tab
|
||||
tmux.until do |lines|
|
||||
assert_operator lines.match_count, :>=, 5
|
||||
assert_equal 0, lines.select_count
|
||||
end
|
||||
tmux.send_keys :Tab, :Tab, :Tab
|
||||
tmux.until do |lines|
|
||||
assert_equal 3, lines.select_count
|
||||
end
|
||||
tmux.send_keys :Enter
|
||||
tmux.until { |lines| assert lines.any_include?('ssh jg@localhost -i /tmp/fzf-test-ssh-') }
|
||||
|
||||
tmux.send_keys 'localhost**', :Tab
|
||||
tmux.until do |lines|
|
||||
assert_operator lines.match_count, :>=, 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class TestBash < TestBase
|
||||
include TestShell
|
||||
include CompletionTest
|
||||
|
||||
def shell
|
||||
:bash
|
||||
end
|
||||
|
||||
def new_shell
|
||||
tmux.prepare
|
||||
tmux.send_keys "FZF_TMUX=1 #{Shell.bash}", :Enter
|
||||
tmux.prepare
|
||||
end
|
||||
|
||||
def test_dynamic_completion_loader
|
||||
tmux.paste 'touch /tmp/foo; _fzf_completion_loader=1'
|
||||
tmux.paste '_completion_loader() { complete -o default fake; }'
|
||||
tmux.paste 'complete -F _fzf_path_completion -o default -o bashdefault fake'
|
||||
tmux.send_keys 'fake /tmp/foo**', :Tab
|
||||
tmux.until { |lines| assert_operator lines.match_count, :>, 0 }
|
||||
tmux.send_keys 'C-c'
|
||||
|
||||
tmux.prepare
|
||||
tmux.send_keys 'fake /tmp/foo'
|
||||
tmux.send_keys :Tab, 'C-u'
|
||||
|
||||
tmux.prepare
|
||||
tmux.send_keys 'fake /tmp/foo**', :Tab
|
||||
tmux.until { |lines| assert_operator lines.match_count, :>, 0 }
|
||||
end
|
||||
end
|
||||
|
||||
class TestZsh < TestBase
|
||||
include TestShell
|
||||
include CompletionTest
|
||||
|
||||
def shell
|
||||
:zsh
|
||||
end
|
||||
|
||||
def new_shell
|
||||
tmux.send_keys "FZF_TMUX=1 #{Shell.zsh}", :Enter
|
||||
tmux.prepare
|
||||
end
|
||||
|
||||
def test_complete_quoted_command
|
||||
tmux.send_keys 'export FZFFOOBAR=BAZ', :Enter
|
||||
['unset', '\unset', "'unset'"].each do |command|
|
||||
tmux.prepare
|
||||
tmux.send_keys "#{command} FZFFOOBR**", :Tab
|
||||
tmux.until { |lines| assert_equal 1, lines.match_count }
|
||||
tmux.send_keys :Enter
|
||||
tmux.until { |lines| assert_equal "#{command} FZFFOOBAR", lines[-1] }
|
||||
tmux.send_keys 'C-c'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class TestFish < TestBase
|
||||
include TestShell
|
||||
|
||||
def shell
|
||||
:fish
|
||||
end
|
||||
|
||||
def new_shell
|
||||
tmux.send_keys 'env FZF_TMUX=1 FZF_DEFAULT_OPTS=--no-scrollbar fish', :Enter
|
||||
tmux.send_keys 'function fish_prompt; end; clear', :Enter
|
||||
tmux.until { |lines| assert_empty lines }
|
||||
end
|
||||
|
||||
def set_var(name, val)
|
||||
tmux.prepare
|
||||
tmux.send_keys "set -g #{name} '#{val}'", :Enter
|
||||
tmux.prepare
|
||||
end
|
||||
end
|
@ -13,7 +13,7 @@ Execute (fzf#run with dir option):
|
||||
|
||||
execute 'lcd' fnameescape(cwd)
|
||||
let result = sort(fzf#run({ 'source': 'git ls-files', 'options': '--filter e', 'dir': g:dir }))
|
||||
AssertEqual ['fzf.vader', 'test_go.rb'], result
|
||||
AssertEqual ['fzf.vader'], result
|
||||
AssertEqual 1, haslocaldir()
|
||||
AssertEqual getcwd(), cwd
|
||||
|
||||
@ -23,8 +23,8 @@ Execute (fzf#run with Funcref command):
|
||||
call add(g:ret, a:e)
|
||||
endfunction
|
||||
let result = sort(fzf#run({ 'source': 'git ls-files', 'sink': function('g:FzfTest'), 'options': '--filter e', 'dir': g:dir }))
|
||||
AssertEqual ['fzf.vader', 'test_go.rb'], result
|
||||
AssertEqual ['fzf.vader', 'test_go.rb'], sort(g:ret)
|
||||
AssertEqual ['fzf.vader'], result
|
||||
AssertEqual ['fzf.vader'], sort(g:ret)
|
||||
|
||||
Execute (fzf#run with string source):
|
||||
let result = sort(fzf#run({ 'source': 'echo hi', 'options': '-f i' }))
|
||||
@ -78,18 +78,18 @@ Execute (fzf#wrap):
|
||||
|
||||
let opts = fzf#wrap('foobar')
|
||||
Log opts
|
||||
AssertEqual '~40%', opts.down
|
||||
AssertEqual 0.9, opts.window.width
|
||||
Assert opts.options =~ '--expect='
|
||||
Assert !has_key(opts, 'sink')
|
||||
Assert has_key(opts, 'sink*')
|
||||
|
||||
let opts = fzf#wrap('foobar', {}, 0)
|
||||
Log opts
|
||||
AssertEqual '~40%', opts.down
|
||||
AssertEqual 0.9, opts.window.width
|
||||
|
||||
let opts = fzf#wrap('foobar', {}, 1)
|
||||
Log opts
|
||||
Assert !has_key(opts, 'down')
|
||||
Assert !has_key(opts, 'window')
|
||||
|
||||
let opts = fzf#wrap('foobar', {'down': '50%'})
|
||||
Log opts
|
||||
@ -148,7 +148,7 @@ Execute (fzf#wrap):
|
||||
|
||||
let g:fzf_colors = { 'fg': ['fg', 'Error'] }
|
||||
let opts = fzf#wrap({})
|
||||
Assert opts.options =~ '^--color=fg:'
|
||||
Assert opts.options =~ '--color=fg:'
|
||||
|
||||
Execute (fzf#shellescape with sh):
|
||||
AssertEqual '''''', fzf#shellescape('', 'sh')
|
Loading…
x
Reference in New Issue
Block a user