mirror of
https://github.com/opf/openproject.git
synced 2026-06-14 03:30:14 +00:00
Harden feature test support helpers
Stabilize shared ng-select interactions for Cuprite and reuse open dropdowns safely in modal-based flows. Also keep filter clearing safe when no value is selected and refresh the My Page drop target after drag-induced DOM updates.
This commit is contained in:
@@ -4,10 +4,10 @@ module Components::Autocompleter
|
||||
module NgSelectAutocompleteHelpers
|
||||
def search_autocomplete(element, query:, results_selector: "body", wait_dropdown_open: true, wait_for_fetched_options: true)
|
||||
SeleniumHubWaiter.wait unless using_cuprite?
|
||||
ng_click_autocompleter(element)
|
||||
|
||||
# Wait for dropdown to open
|
||||
ng_find_dropdown(element, results_selector:) if wait_dropdown_open
|
||||
dropdown_open = ng_dropdown_open?(element, results_selector:) if wait_dropdown_open
|
||||
ng_click_autocompleter(element) unless dropdown_open
|
||||
|
||||
# Wait for autocompleter options to be loaded (data fetching is debounced by 250ms after creation or typing)
|
||||
wait_for_network_idle if using_cuprite? && wait_for_fetched_options
|
||||
@@ -33,27 +33,49 @@ module Components::Autocompleter
|
||||
end
|
||||
|
||||
def ng_click_autocompleter(target)
|
||||
target.click
|
||||
input = ng_select_input(target)
|
||||
|
||||
scroll_to_element(input, block: :nearest)
|
||||
input.click
|
||||
end
|
||||
|
||||
def ng_find_dropdown(element, results_selector: "body")
|
||||
def ng_find_dropdown(element, results_selector: "body", raise_on_missing: true)
|
||||
retry_block do
|
||||
if results_selector
|
||||
results_selector = "#{results_selector} .ng-dropdown-panel" if results_selector == "body"
|
||||
within_window(current_window) do
|
||||
page.find(results_selector, wait: 5)
|
||||
page.find(results_selector, wait: raise_on_missing ? 5 : 0)
|
||||
end
|
||||
else
|
||||
within(element) do
|
||||
page.find("ng-select .ng-dropdown-panel", wait: 5)
|
||||
page.find("ng-select .ng-dropdown-panel", wait: raise_on_missing ? 5 : 0)
|
||||
end
|
||||
end
|
||||
rescue StandardError => e
|
||||
ng_select_input(element)&.click
|
||||
rescue Capybara::ElementNotFound => e
|
||||
return nil unless raise_on_missing
|
||||
|
||||
ng_click_autocompleter(element)
|
||||
raise e
|
||||
end
|
||||
end
|
||||
|
||||
def ng_dropdown_open?(element, results_selector: "body")
|
||||
if results_selector
|
||||
within_window(current_window) do
|
||||
page.has_css?(ng_panel_selector(results_selector), wait: 0)
|
||||
end
|
||||
else
|
||||
element.has_css?("ng-select .ng-dropdown-panel", wait: 0)
|
||||
end
|
||||
end
|
||||
|
||||
def ng_panel_selector(results_selector)
|
||||
return "body .ng-dropdown-panel" if results_selector == "body"
|
||||
return results_selector if results_selector.include?(".ng-dropdown-panel")
|
||||
|
||||
"#{results_selector} .ng-dropdown-panel"
|
||||
end
|
||||
|
||||
def expect_ng_option(element, option, grouping: nil, results_selector: "body", present: true)
|
||||
within(ng_find_dropdown(element, results_selector:)) do
|
||||
if grouping && present
|
||||
@@ -133,7 +155,10 @@ module Components::Autocompleter
|
||||
# clear the ng select field
|
||||
def ng_select_clear(from_element, raise_on_missing: true)
|
||||
if raise_on_missing || from_element.has_css?(".ng-clear-wrapper", visible: :all, wait: 1)
|
||||
from_element.find(".ng-clear-wrapper", visible: :all).click
|
||||
clear_button = from_element.find(".ng-clear-wrapper", visible: :all)
|
||||
|
||||
scroll_to_element(clear_button, block: :nearest)
|
||||
clear_button.click
|
||||
end
|
||||
end
|
||||
|
||||
@@ -143,11 +168,11 @@ module Components::Autocompleter
|
||||
results_selector: "body",
|
||||
wait_dropdown_open: true,
|
||||
wait_for_fetched_options: true)
|
||||
target_dropdown = search_autocomplete(element,
|
||||
query:,
|
||||
results_selector:,
|
||||
wait_dropdown_open:,
|
||||
wait_for_fetched_options:)
|
||||
search_autocomplete(element,
|
||||
query:,
|
||||
results_selector:,
|
||||
wait_dropdown_open:,
|
||||
wait_for_fetched_options:)
|
||||
|
||||
##
|
||||
# If a specific select_text is given, use that to locate the match,
|
||||
|
||||
@@ -79,7 +79,7 @@ module Components
|
||||
|
||||
def drag_to(row, column)
|
||||
handle = drag_handle
|
||||
drop_area = self.class.of(row * 2, column * 2).area
|
||||
target = self.class.of(row * 2, column * 2)
|
||||
|
||||
scroll_to_element(handle)
|
||||
|
||||
@@ -87,13 +87,14 @@ module Components
|
||||
action.click_and_hold(handle.native)
|
||||
end
|
||||
|
||||
scroll_to_element(drop_area)
|
||||
drop_area.hover
|
||||
scroll_to_element(target.area)
|
||||
target.area.hover
|
||||
|
||||
sleep(1)
|
||||
|
||||
# Re-find drop_area to get a fresh native reference after CDK drag has modified the DOM
|
||||
move_to(self.class.of(row * 2, column * 2).area, &:release)
|
||||
# `target.area` calls page.find on each access, so this re-queries the DOM
|
||||
# to get a fresh native reference after CDK drag has updated it.
|
||||
move_to(target.area, &:release)
|
||||
end
|
||||
|
||||
def expect_to_exist
|
||||
|
||||
@@ -224,7 +224,7 @@ module Components
|
||||
end
|
||||
|
||||
def clear_filter_value(field)
|
||||
ng_select_clear(page.find("#filter_#{field} ng-select"))
|
||||
ng_select_clear(page.find("#filter_#{field} ng-select"), raise_on_missing: false)
|
||||
end
|
||||
|
||||
def open_autocompleter(id)
|
||||
|
||||
@@ -227,7 +227,17 @@ class EditField
|
||||
|
||||
if autocompleter_field?
|
||||
if multi
|
||||
page.find(".ng-value-label", visible: :all, text: content).sibling(".ng-value-icon").click
|
||||
remove_icon = field_container
|
||||
.find(".ng-value-label", visible: :all, text: content)
|
||||
.sibling(".ng-value-icon")
|
||||
|
||||
begin
|
||||
scroll_to_element(remove_icon, block: :nearest)
|
||||
remove_icon.click
|
||||
rescue Capybara::Cuprite::MouseEventFailed
|
||||
# Cuprite-only: bypass Chrome's overlap check when the chip icon is obscured.
|
||||
remove_icon.trigger("click")
|
||||
end
|
||||
else
|
||||
ng_select_clear(field_container)
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user