Make some feature specs faster

`raise_if_found` helpers were uselessly waiting 5 seconds for the
element to show up. Using regular capybara matchers saves the waiting
time.

Also, `close_autocompleter` was waiting for it to be visible, or even
opening it to be able to close it. If it is not open, returning early
saves time too.

About `ensure_value_is_input_correctly`, it is more optmistic: it first
tries without waiting, and if the input value is not correctly set, it
waits as it did before.

For `spec/features/work_packages/table/queries/filter_spec.rb`:
- before: 2 minutes 41 seconds
- after: 1 minute 15.81 seconds
This commit is contained in:
Christophe Bliard
2023-03-08 15:42:17 +01:00
parent 2bc0f56dec
commit a698b2eca3
6 changed files with 47 additions and 82 deletions
@@ -147,7 +147,7 @@ describe 'filter work packages', js: true do
filters.open_autocompleter :status
expect(page).to have_selector('.ng-option', text: closed_status.name)
expect(page).to have_no_selector('.ng-option', text: status.name)
expect(page).not_to have_selector('.ng-option', text: status.name)
end
end
+1 -1
View File
@@ -52,7 +52,7 @@ module Components
end
def expect_closed
page.raise_if_found(autocompleter_selector)
expect(page).not_to have_selector(autocompleter_selector)
end
def search(query)
@@ -128,7 +128,7 @@ module Components
elsif value
expect_value(id, Array(value))
else
expect(page).to have_no_selector("#values-#{id}")
expect(page).not_to have_selector("#values-#{id}")
end
end
@@ -148,8 +148,8 @@ module Components
id = selector || name.downcase
retry_block do
page.raise_if_found_select("operators-#{id}")
page.raise_if_found_select("values-#{id}")
expect(page).not_to have_select("operators-#{id}")
expect(page).not_to have_select("values-#{id}")
end
end
@@ -164,21 +164,24 @@ module Components
end
def open_autocompleter(id)
input = page.all("#filter_#{id} .advanced-filters--filter-value .ng-input input").first
if input
input.click
input
end
with_filter_input_element(id, &:click)
end
def close_autocompleter(id)
input = open_autocompleter(id)
input&.send_keys :escape
with_filter_input_element(id) do |input|
input.send_keys :escape
end
end
protected
def with_filter_input_element(id)
filter_value_element = page.find("#filter_#{id} .advanced-filters--filter-value", match: :first)
return unless filter_value_element.has_selector?(".ng-input input", wait: false)
yield filter_value_element.find(".ng-input input")
end
def filter_button
find(button_selector)
end
@@ -193,6 +196,7 @@ module Components
def set_value(id, value)
retry_block do
# wait for filter to be present
filter_element = page.find("#filter_#{id}")
if filter_element.has_selector?("[data-qa-selector='op-multi-date-picker']", wait: false)
datepicker = Components::WorkPackageDatepicker.new
@@ -221,9 +225,11 @@ module Components
end
def expect_missing_value(id, value)
if page.has_selector?("#filter_#{id} .ng-select-container")
# wait for filter to be present
filter_element = page.find("#filter_#{id}")
if filter_element.has_selector?(".ng-select-container", wait: false)
Array(value).each do |val|
dropdown = search_autocomplete page.find("#filter_#{id}"),
dropdown = search_autocomplete filter_element,
query: val,
results_selector: '.ng-dropdown-panel-items'
expect(dropdown).not_to have_selector('.ng-option', text: val)
@@ -232,8 +238,9 @@ module Components
end
def expect_value_placeholder(id)
if page.has_selector?("#filter_#{id} .ng-select-container")
expect(page).to have_selector("#filter_#{id} .ng-placeholder", text: I18n.t('js.placeholders.selection'))
filter_element = page.find("#filter_#{id}")
if filter_element.has_selector?(".ng-select-container", wait: false)
expect(filter_element).to have_selector(".ng-placeholder", text: I18n.t('js.placeholders.selection'))
else
raise "Non ng-select may not have placeholders currently"
end
@@ -245,15 +252,17 @@ module Components
value.each do |v|
expect(page).to have_selector("#values-#{id} .ng-value-label", text: v)
end
elsif page.has_selector?("#filter_#{id} [data-qa-selector='op-multi-date-picker']")
elsif page.has_selector?("#filter_#{id} [data-qa-selector='op-multi-date-picker']", wait: false)
expected_value =
if value[1]
"#{value[0]} - #{value[1]}"
elsif value[0]
value[0].to_s
else
"-"
end
input = page.find("#filter_#{id} [data-qa-selector='op-multi-date-picker'] input")
if value[1]
expect(input.value).to eql("#{value[0]} - #{value[1]}")
elsif value[0]
expect(input.value).to eql("#{value[0]}")
else
expect(input.value).to eql("-")
end
expect(input.value).to eql(expected_value)
else
page.all('input').each_with_index do |input, index|
expect(input.value).to eql(value[index])
-50
View File
@@ -1,50 +0,0 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2023 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
# Extending Capybara to check or raise for an element
module Capybara
class Session
def raise_if_found(condition, *args, **kw_args)
raise_if_has_selector?(:has_selector?, condition, *args, **kw_args)
end
def raise_if_found_field(condition, *args, **kw_args)
raise_if_has_selector?(:has_field?, condition, *args, **kw_args)
end
def raise_if_found_select(condition, *args, **kw_args)
raise_if_has_selector?(:has_select?, condition, *args, **kw_args)
end
def raise_if_has_selector?(method, condition, *args, **kw_args)
found = public_send(method, condition, *args, **kw_args)
raise "Expected not to find field #{condition}" if found
end
end
end
@@ -107,7 +107,7 @@ module Pages
retry_block(args: { tries: 3, base_interval: 5 }) do
within(table_container) do
work_packages.each do |wp|
page.raise_if_found(".wp-row-#{wp.id} td.subject", text: wp.subject, wait: 1)
expect(page).not_to have_selector(".wp-row-#{wp.id} td.subject", text: wp.subject)
end
end
end
+12 -6
View File
@@ -31,12 +31,18 @@
# https://bugs.chromium.org/p/chromedriver/issues/detail?id=1771
module SeleniumWorkarounds
def ensure_value_is_input_correctly(input, value:)
# Wait a bit to insert the value
sleep(0.5)
input.set value
sleep(0.5)
correctly_set = false
# Wait longer and longer to set the value, until it is set correctly.
# The bug may be fixed by now...
[0, 0.5, 1].each do |waiting_time|
sleep(waiting_time)
input.set value
sleep(waiting_time)
found_value = input.value
raise "Found value #{found_value}, but expected #{value}." unless found_value == value
correctly_set = (input.value == value)
break if correctly_set
end
raise "Found value #{found_value}, but expected #{value}." unless correctly_set
end
end