0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-06 13:08:40 +08:00
discourse/spec/system/search_shortcut_variation_spec.rb
Régis Hanol 3709d8f3e3
FIX: Hand off search cleanly between welcome banner and header search (#42018)
Previously, the header search field appeared as soon as the welcome
banner was no longer fully visible, leaving both search bars on screen
and interactive at once; since they share one search service, a single
search could show its results in both panels, the banner's open results
panel could overlay and swallow clicks aimed at the header field, and
typing into the superseded banner input ran searches with no visible
results.

This change bases the switch on the banner's search bar itself: the
banner remains the only search UI while any part of its input is below
the header, and the header search replaces it exactly when the input is
fully tucked away — with focus and the open results panel following the
handoff in both directions, stray focus on the superseded input
redirected to the active one, and hidden menus closed so a dismissed
panel stays dismissed.

Note the intentional behavior change: the header search field now
appears slightly later when scrolling (once the banner search bar is
fully under the header, rather than on the first pixel of scroll).

Internal topic: t/188511
2026-07-28 15:56:20 +02:00

136 lines
5 KiB
Ruby
Vendored

# frozen_string_literal: true
describe "Search | Shortcuts for variations of search input" do
fab!(:current_user, :user)
let(:welcome_banner) { PageObjects::Components::WelcomeBanner.new }
let(:search_page) { PageObjects::Pages::Search.new }
before { sign_in(current_user) }
def expect_search_shortcut_to_toggle(input_id)
send_keys("/")
expect(search_page).to have_search_menu
expect(page).to have_css("##{input_id}:focus")
send_keys(:escape)
expect(search_page).to have_no_search_menu_visible
end
context "when search_experience is search_field" do
before do
Fabricate(:theme_site_setting_with_service, name: "search_experience", value: "search_field")
end
context "when enable_welcome_banner is true" do
before do
Fabricate(:theme_site_setting_with_service, name: "enable_welcome_banner", value: true)
end
it "displays and focuses welcome banner search when / is pressed and hides it when Escape is pressed" do
visit("/")
expect(welcome_banner).to be_visible
expect_search_shortcut_to_toggle("welcome-banner-search-input")
end
context "when welcome banner is not in the viewport" do
it "displays and focuses header search when / is pressed and hides it when Escape is pressed" do
visit("/")
expect(welcome_banner).to be_visible
fake_scroll_down_long
expect(search_page).to have_search_field
expect(welcome_banner).to be_invisible
expect_search_shortcut_to_toggle("header-search-input")
end
it "moves the search menu and focus between the welcome banner and the header search as the user scrolls" do
visit("/")
expect(welcome_banner).to be_visible
welcome_banner.open_search_menu
expect(welcome_banner).to have_search_menu
fake_scroll_down_long
expect(search_page).to have_search_field
expect(page).to have_css("#header-search-input:focus")
expect(search_page).to have_header_search_menu
expect(welcome_banner).to have_no_search_menu
page.execute_script(
"document.getElementById('welcome-banner-search-input').focus({ preventScroll: true })",
)
expect(page).to have_css("#header-search-input:focus")
expect(welcome_banner).to have_no_search_menu
page.scroll_to(0, 0)
expect(search_page).to have_no_search_field
expect(page).to have_css("#welcome-banner-search-input:focus")
expect(welcome_banner).to have_search_menu
end
end
end
context "when enable_welcome_banner is false" do
before do
Fabricate(:theme_site_setting_with_service, name: "enable_welcome_banner", value: false)
end
it "displays and focuses header search when / is pressed and hides it when Escape is pressed" do
visit("/")
expect(welcome_banner).to be_hidden
expect_search_shortcut_to_toggle("header-search-input")
end
end
end
context "when search_experience is search_icon" do
before do
Fabricate(:theme_site_setting_with_service, name: "search_experience", value: "search_icon")
end
context "when enable_welcome_banner is true" do
before do
Fabricate(:theme_site_setting_with_service, name: "enable_welcome_banner", value: true)
end
it "displays and focuses welcome banner search when / is pressed and hides it when Escape is pressed" do
visit("/")
expect(welcome_banner).to be_visible
expect_search_shortcut_to_toggle("welcome-banner-search-input")
end
context "when welcome banner is not in the viewport" do
it "displays and focuses search icon search when / is pressed and hides it when Escape is pressed" do
visit("/")
expect(welcome_banner).to be_visible
fake_scroll_down_long
expect(search_page).to have_search_icon
expect(welcome_banner).to be_invisible
expect_search_shortcut_to_toggle("icon-search-input")
end
end
end
context "when enable_welcome_banner is false" do
before do
Fabricate(:theme_site_setting_with_service, name: "enable_welcome_banner", value: false)
end
it "displays and focuses search icon search when / is pressed and hides it when Escape is pressed" do
visit("/")
expect(welcome_banner).to be_hidden
expect_search_shortcut_to_toggle("icon-search-input")
end
# This search menu only shows within a topic, not in other pages on the site,
# unlike header search which is always visible.
context "when within a topic with 20+ posts" do
fab!(:topic)
fab!(:posts) { Fabricate.times(21, :post, topic: topic) }
it "opens search on first press of /, and closes when Escape is pressed" do
visit "/t/#{topic.slug}/#{topic.id}"
expect_search_shortcut_to_toggle("icon-search-input")
end
end
end
end
end