mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-05-26 01:04:55 +08:00
## Requirements Initially defined in https://meta.discourse.org/t/software-engineer-frontend-ember-js-yuriy-kurant/353612/14?u=yaran. 1. On mobile devices and tablets, users can open the search input field by tapping the search icon 2. When opened, the search input takes over the entire header area: - Users can tap the sliders icon to navigate to the advanced search page (/search) - Users can tap Cancel to close search input 3. After submitting a search, results area will take over the entire screen: - Users can tap the X icon to clear the search term from the input field - Users can tap Cancel to close search results area and return to their previous page (i.e. search area overlays content) ## Implementation 1. When opened, the search input takes over the entire header area: - changed panel width from `90vw` to `100vw` - on initial render (when search input is empty), search panel hovers over the header section only (doesn't cover main content below) - quick tip and recent searches lists are not displayed on mobile view 2. Tap on the sliders icon navigates to the advanced search page (`/search`) 3. Tap on the **Cancel** button: - closes search menu - if the search term is present, it is cleared 4. Tap on the left-hand side **Search** icon triggers a topics search ## Dev notes 1. Added `// TODO` questioning `search` service `noResults` default value of `false` 2. Added animation on toggling header search panel (created `delayed-destroy` custom modifier) 3. Extracted in-context search filters into a standalone component `search-menu/active-filters`: - mobile: active filters below search input - desktop: active filters inside search input 3. Removed unnecessary top padding when search results are empty 4. Added `data-test-` attrs for Ember tests. Benefits: - semantically `data-test-` attrs indicate that these parts of the layout are covered with tests - decouples selector dependency on `id/class` names for testing purposes - eliminates risk of broken tests due to `id/class` name changes
127 lines
3.2 KiB
Ruby
Vendored
127 lines
3.2 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
module PageObjects
|
|
module Pages
|
|
class Search < PageObjects::Pages::Base
|
|
def type_in_search(input)
|
|
find("input.full-page-search").send_keys(input)
|
|
self
|
|
end
|
|
|
|
def type_in_search_menu(input)
|
|
find(".search-input--header input").send_keys(input)
|
|
self
|
|
end
|
|
|
|
def click_search_menu_link
|
|
find(".search-menu .results .search-link").click
|
|
end
|
|
|
|
def clear_search_input
|
|
find("input.full-page-search").set("")
|
|
self
|
|
end
|
|
|
|
def has_heading_text?(text)
|
|
has_selector?("h1.search-page-heading", text: text)
|
|
end
|
|
|
|
def has_no_heading_text?(text)
|
|
has_no_selector?("h1.search-page-heading", text: text)
|
|
end
|
|
|
|
def click_search_button
|
|
find(".search-cta").click
|
|
end
|
|
|
|
def click_search_icon
|
|
find(".d-header #search-button").click
|
|
end
|
|
|
|
def click_advanced_search_icon
|
|
find(".show-advanced-search").click
|
|
end
|
|
|
|
def click_in_posts_by_user
|
|
find(".search-menu-container .search-menu-assistant-item").click
|
|
end
|
|
|
|
def click_first_topic
|
|
find(".topic-list-body tr:first-of-type").click
|
|
end
|
|
|
|
def has_search_menu_visible?
|
|
page.has_css?(".search-menu .search-menu-panel", visible: true)
|
|
end
|
|
|
|
# This is used for cases like header and welcome banner search,
|
|
# where we show the search results with a quick tip, but the panel
|
|
# itself is not technically "visible" in CSS terms.
|
|
def has_search_menu?
|
|
page.has_css?(".search-menu .search-menu-panel", visible: false)
|
|
end
|
|
|
|
def has_no_search_menu_visible?
|
|
page.has_no_css?(".search-menu .search-menu-panel")
|
|
end
|
|
|
|
SEARCH_ICON_SELECTOR = "#search-button.btn-icon"
|
|
SEARCH_FIELD_SELECTOR = ".floating-search-input .search-menu"
|
|
SEARCH_RESULT_SELECTOR = ".search-results .fps-result"
|
|
|
|
def has_search_icon?
|
|
page.has_selector?(SEARCH_ICON_SELECTOR, visible: true)
|
|
end
|
|
|
|
def has_no_search_icon?
|
|
page.has_no_selector?(SEARCH_ICON_SELECTOR)
|
|
end
|
|
|
|
def has_search_field?
|
|
page.has_selector?(SEARCH_FIELD_SELECTOR, visible: true)
|
|
end
|
|
|
|
def has_no_search_field?
|
|
page.has_no_selector?(SEARCH_FIELD_SELECTOR)
|
|
end
|
|
|
|
def has_topic_title_for_first_search_result?(title)
|
|
page.has_css?(".search-menu .results .search-result-topic", text: title)
|
|
end
|
|
|
|
def has_search_result?
|
|
page.has_selector?(SEARCH_RESULT_SELECTOR)
|
|
end
|
|
|
|
def has_no_search_result?
|
|
page.has_no_selector?(SEARCH_RESULT_SELECTOR)
|
|
end
|
|
|
|
def has_warning_message?
|
|
page.has_selector?(".search-results .warning")
|
|
end
|
|
|
|
def has_found_no_results?
|
|
page.has_css?(".search-menu-container .results .no-results")
|
|
end
|
|
|
|
def search_term(id = "icon-search-input")
|
|
page.find("##{id}").value
|
|
end
|
|
|
|
SEARCH_PAGE_SELECTOR = "body.search-page"
|
|
|
|
def active?
|
|
has_css?(SEARCH_PAGE_SELECTOR)
|
|
end
|
|
|
|
def not_active?
|
|
has_no_css?(SEARCH_PAGE_SELECTOR)
|
|
end
|
|
|
|
def browser_search_shortcut
|
|
page.send_keys([PLATFORM_KEY_MODIFIER, "f"])
|
|
end
|
|
end
|
|
end
|
|
end
|