Files
fzf/test/test_server.rb
T
Junegunn Choi 7e6339979f
CodeQL / Analyze (go) (push) Canceled after 0s
build / build (push) Canceled after 0s
Test fzf on macOS / build (push) Canceled after 0s
Fix stale progress in --listen status payload (#4907)
- progress was set to 100 by every UpdateList, partial results included,
  and never reset when a search started
- So a GET could report a new query, the previous result set, and
  progress 100, and a client had no way to tell it was stale
- Now cleared where the search is requested and set to 100 only on the
  final result. Query and the reset happen in the same locked section
  that dumpStatus locks, so query == X with progress 100 means the
  matches belong to X

Fix #4903
2026-09-06 19:36:40 +09:00

111 lines
4.4 KiB
Ruby

# 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.match_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])
# No positions when query is empty
state[:matches].each do |m|
assert_nil m[:positions]
end
assert_nil state[:current][:positions] if state[:current]
# Positions with a single-character query
Net::HTTP.post(fn.call, 'change-query(1)')
tmux.until { |lines| assert_equal 2, lines.match_count }
state = JSON.parse(Net::HTTP.get(fn.call), symbolize_names: true)
assert_equal [0], state[:current][:positions]
state[:matches].each do |m|
assert_includes m[:text], '1'
assert_equal [m[:text].index('1')], m[:positions]
end
# Positions with a multi-character query; verify sorted ascending
Net::HTTP.post(fn.call, 'change-query(10)')
tmux.until { |lines| assert_equal 1, lines.match_count }
state = JSON.parse(Net::HTTP.get(fn.call), symbolize_names: true)
assert_equal '10', state[:current][:text]
assert_equal [0, 1], state[:current][:positions]
assert_equal state[:current][:positions], state[:current][:positions].sort
# No match - no current item
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_progress
tmux.send_keys "seq 10 | #{FZF} --listen 6266", :Enter
tmux.until { |lines| assert_equal 10, lines.match_count }
uri = URI('http://localhost:6266')
state = -> { JSON.parse(Net::HTTP.get(uri), symbolize_names: true) }
# Idle: the last search is complete
assert_equal 100, state.call[:progress]
# While a search is running, progress is not left at 100 from the
# previous one, so it can tell a settled snapshot from a stale one
Net::HTTP.post(uri, 'reload(sleep 1; seq 100)')
tmux.until { assert_equal 0, state.call[:progress] }
# Settled: matches belong to the snapshot that reports 100
tmux.until { |lines| assert_equal 100, lines.match_count }
tmux.until do
st = state.call
assert_equal 100, st[:progress]
assert_equal 100, st[:matchCount]
end
end
def test_listen_with_api_key
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.match_count }
# Incorrect API Key
[nil, { 'x-api-key' => '' }, { 'x-api-key' => '124abc' }].each do |headers|
res = Net::HTTP.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
res = Net::HTTP.get_response(uri, 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(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] }
res = Net::HTTP.get_response(uri, headers)
assert_equal '200', res.code
assert_equal 'yo', JSON.parse(res.body, symbolize_names: true)[:query]
end
end
end