Maintenance: Stabilize tests with general wait_for_ajax_empty approach and some fixed tests.

This commit is contained in:
Rolf Schmidt 2021-06-15 06:26:52 +00:00 committed by Thorsten Eckel
parent 1242121de7
commit c44196d7ab
24 changed files with 415 additions and 199 deletions

View file

@ -690,6 +690,7 @@ Metrics/ModuleLength:
- 'lib/signature_detection.rb' - 'lib/signature_detection.rb'
- 'lib/static_assets.rb' - 'lib/static_assets.rb'
- 'lib/transaction_dispatcher.rb' - 'lib/transaction_dispatcher.rb'
- 'spec/support/capybara/common_actions.rb'
Metrics/PerceivedComplexity: Metrics/PerceivedComplexity:
Exclude: Exclude:

View file

@ -1038,12 +1038,13 @@ class App.ControllerTable extends App.Controller
# update store # update store
@preferencesStore('order', 'customOrderBy', @orderBy) @preferencesStore('order', 'customOrderBy', @orderBy)
@preferencesStore('order', 'customOrderDirection', @orderDirection) @preferencesStore('order', 'customOrderDirection', @orderDirection)
render = =>
@renderTableFull(false, skipHeadersResize: true)
App.QueueManager.add('tableRender', render)
if @sortRenderCallback if @sortRenderCallback
App.QueueManager.add('tableRender', @sortRenderCallback) App.QueueManager.add('tableRender', @sortRenderCallback)
else
render = =>
@renderTableFull(false, skipHeadersResize: true)
App.QueueManager.add('tableRender', render)
App.QueueManager.run('tableRender') App.QueueManager.run('tableRender')

View file

@ -68,9 +68,11 @@ module BrowserTestHelper
# await_empty_ajax_queue # await_empty_ajax_queue
# #
def await_empty_ajax_queue def await_empty_ajax_queue
wait(5, interval: 0.5).until_constant do wait(5, interval: 0.1).until_constant do
page.evaluate_script('App.Ajax.queue().length').zero? page.evaluate_script('App.Ajax.queue().length').zero?
end end
rescue
nil
end end
# Moves the mouse from its current position by the given offset. # Moves the mouse from its current position by the given offset.
@ -112,6 +114,7 @@ module BrowserTestHelper
# #
def release_mouse def release_mouse
page.driver.browser.action.release.perform page.driver.browser.action.release.perform
await_empty_ajax_queue
end end
class Waiter < SimpleDelegator class Waiter < SimpleDelegator

View file

@ -38,6 +38,8 @@ module CommonActions
wait(4).until_exists do wait(4).until_exists do
current_login current_login
end end
await_empty_ajax_queue
end end
# Checks if the current session is logged in. # Checks if the current session is logged in.
@ -120,6 +122,16 @@ module CommonActions
route = "/##{route}" route = "/##{route}"
end end
super(route) super(route)
# wait for AJAX requets only on WebApp visits
return if !route.start_with?('/#')
return if route == '/#logout'
# make sure all AJAX requests are done
await_empty_ajax_queue
# make sure loading is completed (e.g. ticket zoom may take longer)
expect(page).to have_no_css('.icon-loading', wait: 30)
end end
# Overwrites the global Capybara.always_include_port setting (true) # Overwrites the global Capybara.always_include_port setting (true)

View file

@ -34,3 +34,108 @@ class Capybara::Node::Element
raise "Element still moving after #{checks} checks" raise "Element still moving after #{checks} checks"
end end
end end
module ZammadCapybarActionDelegator
def select(*)
super.tap do
await_empty_ajax_queue
end
end
def click(*)
super.tap do
await_empty_ajax_queue
end
end
def click_on(*)
super.tap do
await_empty_ajax_queue
end
end
def click_link_or_button(*)
super.tap do
await_empty_ajax_queue
end
end
def click_button(*)
super.tap do
await_empty_ajax_queue
end
end
def select_option(*)
super.tap do
await_empty_ajax_queue
end
end
def send_keys(*)
super.tap do
await_empty_ajax_queue
end
end
end
module ZammadCapybarSelectorDelegator
def find_field(*)
ZammadCapybaraElementDelegator.new(element: super, context: self)
end
def find_button(*)
ZammadCapybaraElementDelegator.new(element: super, context: self)
end
def find_by_id(*)
ZammadCapybaraElementDelegator.new(element: super, context: self)
end
def find_link(*)
ZammadCapybaraElementDelegator.new(element: super, context: self)
end
def find(*)
ZammadCapybaraElementDelegator.new(element: super, context: self)
end
def first(*)
ZammadCapybaraElementDelegator.new(element: super, context: self)
end
def all(*)
super.map { |element| ZammadCapybaraElementDelegator.new(element: element, context: self) }
end
end
class ZammadCapybaraSessionDelegator < SimpleDelegator
extend Forwardable
def_delegator :@context, :await_empty_ajax_queue
include ZammadCapybarSelectorDelegator
def initialize(context:, element:)
@context = context
super(element)
end
end
class ZammadCapybaraElementDelegator < ZammadCapybaraSessionDelegator
include ZammadCapybarActionDelegator
end
module CapybaraCustomExtensions
include ZammadCapybarActionDelegator
include ZammadCapybarSelectorDelegator
def page(*)
ZammadCapybaraSessionDelegator.new(element: super, context: self)
end
end
RSpec.configure do |config|
config.include CapybaraCustomExtensions, type: :system
end

View file

@ -15,12 +15,12 @@ RSpec.describe 'Authentication', type: :system do
it 'Logout' do it 'Logout' do
logout logout
expect_current_route 'login', wait: 2 expect_current_route 'login', wait: 10
end end
it 'will unset user attributes after logout' do it 'will unset user attributes after logout' do
logout logout
expect_current_route 'login', wait: 2 expect_current_route 'login', wait: 10
visit '/#signup' visit '/#signup'
@ -31,20 +31,20 @@ RSpec.describe 'Authentication', type: :system do
it 'Login and redirect to requested url', authenticated_as: false do it 'Login and redirect to requested url', authenticated_as: false do
visit 'ticket/zoom/1' visit 'ticket/zoom/1'
expect_current_route 'login', wait: 2 expect_current_route 'login', wait: 10
login( login(
username: 'master@example.com', username: 'master@example.com',
password: 'test', password: 'test',
) )
expect_current_route 'ticket/zoom/1', wait: 2 expect_current_route 'ticket/zoom/1', wait: 10
end end
it 'Login and redirect to requested url via external authentication', authenticated_as: false do it 'Login and redirect to requested url via external authentication', authenticated_as: false do
visit 'ticket/zoom/1' visit 'ticket/zoom/1'
expect_current_route 'login', wait: 2 expect_current_route 'login', wait: 10
# simulate jump to external ressource # simulate jump to external ressource
visit 'https://www.zammad.org' visit 'https://www.zammad.org'
@ -59,7 +59,7 @@ RSpec.describe 'Authentication', type: :system do
# jump back and check if origin requested url is shown # jump back and check if origin requested url is shown
visit '' visit ''
expect_current_route 'ticket/zoom/1', wait: 2 expect_current_route 'ticket/zoom/1', wait: 10
expect(current_login).to eq('master@example.com') expect(current_login).to eq('master@example.com')
end end

View file

@ -30,7 +30,6 @@ RSpec.describe 'Dashboard', type: :system, authenticated_as: true do
fill_in 'Lastname', with: 'Braun' fill_in 'Lastname', with: 'Braun'
fill_in 'Email', with: 'nick.braun@zammad.org' fill_in 'Email', with: 'nick.braun@zammad.org'
click_on 'Invite' click_on 'Invite'
await_empty_ajax_queue
expect(User.find_by(firstname: 'Nick').roles).to eq([Role.find_by(name: 'Public')]) expect(User.find_by(firstname: 'Nick').roles).to eq([Role.find_by(name: 'Public')])
end end
end end
@ -42,6 +41,7 @@ RSpec.describe 'Dashboard', type: :system, authenticated_as: true do
before do before do
ensure_websocket(check_if_pinged: false) ensure_websocket(check_if_pinged: false)
sleep 3 # fast relog causes raise conditions in websocket server
end end
context 'Logout by frontend plugin - Default', authenticated_as: :authenticate do context 'Logout by frontend plugin - Default', authenticated_as: :authenticate do

View file

@ -1,46 +1,46 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/ # Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
RSpec.shared_examples 'pagination' do |model:, klass:, path:, sort_by: :name| RSpec.shared_examples 'pagination' do |model:, klass:, path:, sort_by: :name|
def prepare(model) let(:model) { model }
def authenticate
create_list(model, 500) create_list(model, 500)
true
end end
it 'does paginate' do it 'does paginate', authenticated_as: :authenticate do
prepare(model)
visit path visit path
refresh # more stability
expect(page).to have_css('.js-pager', wait: 10) expect(page).to have_css('.js-pager', wait: 10)
class_page1 = klass.order(sort_by => :asc, id: :asc).offset(50).first class_page1 = klass.order(sort_by => :asc, id: :asc).offset(50).first
expect(page).to have_text(class_page1.name, wait: 10) expect(page).to have_text(class_page1.name, wait: 10)
expect(page).to have_css('.js-page.is-selected', text: '1')
page.first('.js-page', text: '2').click page.first('.js-page', text: '2', wait: 10).click
await_empty_ajax_queue
class_page2 = klass.order(sort_by => :asc, id: :asc).offset(175).first class_page2 = klass.order(sort_by => :asc, id: :asc).offset(175).first
expect(page).to have_text(class_page2.name, wait: 10) expect(page).to have_text(class_page2.name, wait: 10)
expect(page).to have_css('.js-page.is-selected', text: '2')
page.first('.js-page', text: '3').click page.first('.js-page', text: '3', wait: 10).click
await_empty_ajax_queue
class_page3 = klass.order(sort_by => :asc, id: :asc).offset(325).first class_page3 = klass.order(sort_by => :asc, id: :asc).offset(325).first
expect(page).to have_text(class_page3.name, wait: 10) expect(page).to have_text(class_page3.name, wait: 10)
expect(page).to have_css('.js-page.is-selected', text: '3')
page.first('.js-page', text: '4').click page.first('.js-page', text: '4', wait: 10).click
await_empty_ajax_queue
class_page4 = klass.order(sort_by => :asc, id: :asc).offset(475).first class_page4 = klass.order(sort_by => :asc, id: :asc).offset(475).first
expect(page).to have_text(class_page4.name, wait: 10) expect(page).to have_text(class_page4.name, wait: 10)
expect(page).to have_css('.js-page.is-selected', text: '4')
page.first('.js-page', text: '1').click page.first('.js-page', text: '1', wait: 10).click
await_empty_ajax_queue
page.first('.js-tableHead[data-column-key=name]').click page.first('.js-tableHead[data-column-key=name]').click
await_empty_ajax_queue
expect(page).to have_text(class_page1.name, wait: 10) expect(page).to have_text(class_page1.name, wait: 10)
expect(page).to have_css('.js-page.is-selected', text: '1')
page.first('.js-tableHead[data-column-key=name]').click page.first('.js-tableHead[data-column-key=name]').click
await_empty_ajax_queue
class_last = klass.order(sort_by => :desc).first class_last = klass.order(sort_by => :desc).first
expect(page).to have_text(class_last.name, wait: 10) expect(page).to have_text(class_last.name, wait: 10)
end end

View file

@ -42,12 +42,12 @@ RSpec.describe 'Manage > Users', type: :system do
visit 'manage/users' visit 'manage/users'
within(:active_content) do within(:active_content) do
row = find("tr[data-id=\"#{user.id}\"]") row = find("tr[data-id=\"#{user.id}\"]", wait: 10)
row.find('.js-action').click row.find('.js-action').click
row.find('.js-switchTo').click row.find('.js-switchTo').click
end end
await_empty_ajax_queue expect(page).to have_text("Zammad looks like this for \"#{user.firstname} #{user.lastname}\"", wait: 10)
end end
end end
end end

View file

@ -63,8 +63,6 @@ RSpec.describe 'Admin Panel > Objects', type: :system, authenticated_as: true do
'nulloption' => true, 'nulloption' => true,
'maxlength' => 255 } 'maxlength' => 255 }
await_empty_ajax_queue
expect(ObjectManager::Attribute.last.data_option).to eq(expected_data_options) expect(ObjectManager::Attribute.last.data_option).to eq(expected_data_options)
end end
end end

View file

@ -15,6 +15,6 @@ RSpec.describe 'System > Translations', type: :system do
click '.js-syncChanges' click '.js-syncChanges'
modal_ready && modal_disappear # make sure test is not terminated while modal is visible modal_disappear # make sure test is not terminated while modal is visible
end end
end end

View file

@ -204,8 +204,6 @@ RSpec.describe 'Ticket Create', type: :system do
encrypt_button = find('.js-securityEncrypt', wait: 5) encrypt_button = find('.js-securityEncrypt', wait: 5)
sign_button = find('.js-securitySign', wait: 5) sign_button = find('.js-securitySign', wait: 5)
await_empty_ajax_queue
active_button_class = '.btn--active' active_button_class = '.btn--active'
expect(encrypt_button.matches_css?(active_button_class, wait: 2)).to be(encrypt) expect(encrypt_button.matches_css?(active_button_class, wait: 2)).to be(encrypt)
expect(sign_button.matches_css?(active_button_class, wait: 2)).to be(sign) expect(sign_button.matches_css?(active_button_class, wait: 2)).to be(sign)
@ -234,8 +232,6 @@ RSpec.describe 'Ticket Create', type: :system do
within(:active_content) do within(:active_content) do
use_template(template) use_template(template)
await_empty_ajax_queue
select new_group.name, from: 'group_id' select new_group.name, from: 'group_id'
end end
end end
@ -378,7 +374,6 @@ RSpec.describe 'Ticket Create', type: :system do
click_on 'Link issue' click_on 'Link issue'
fill_in 'link', with: ENV['GITLAB_ISSUE_LINK'] fill_in 'link', with: ENV['GITLAB_ISSUE_LINK']
click_on 'Submit' click_on 'Submit'
await_empty_ajax_queue
# verify issue # verify issue
content = find('.sidebar-git-issue-content') content = find('.sidebar-git-issue-content')
@ -390,7 +385,6 @@ RSpec.describe 'Ticket Create', type: :system do
# create Ticket # create Ticket
click '.js-submit' click '.js-submit'
await_empty_ajax_queue
# check stored data # check stored data
expect(Ticket.last.preferences[:gitlab][:issue_links][0]).to eq(ENV['GITLAB_ISSUE_LINK']) expect(Ticket.last.preferences[:gitlab][:issue_links][0]).to eq(ENV['GITLAB_ISSUE_LINK'])
@ -432,7 +426,6 @@ RSpec.describe 'Ticket Create', type: :system do
click_on 'Link issue' click_on 'Link issue'
fill_in 'link', with: ENV['GITHUB_ISSUE_LINK'] fill_in 'link', with: ENV['GITHUB_ISSUE_LINK']
click_on 'Submit' click_on 'Submit'
await_empty_ajax_queue
# verify issue # verify issue
content = find('.sidebar-git-issue-content') content = find('.sidebar-git-issue-content')
@ -444,7 +437,6 @@ RSpec.describe 'Ticket Create', type: :system do
# create Ticket # create Ticket
click '.js-submit' click '.js-submit'
await_empty_ajax_queue
# check stored data # check stored data
expect(Ticket.last.preferences[:github][:issue_links][0]).to eq(ENV['GITHUB_ISSUE_LINK']) expect(Ticket.last.preferences[:github][:issue_links][0]).to eq(ENV['GITHUB_ISSUE_LINK'])

View file

@ -35,7 +35,7 @@ RSpec.describe 'Ticket Update', type: :system do
select('closed', from: 'state_id') select('closed', from: 'state_id')
click('.js-attributeBar .js-submit') click('.js-attributeBar .js-submit')
expect(page).to have_no_css('.js-submitDropdown .js-submit[disabled]', wait: 2) expect(page).to have_no_css('.js-submitDropdown .js-submit[disabled]', wait: 10)
end end
# the update should have failed and thus the ticket is still in the new state # the update should have failed and thus the ticket is still in the new state
@ -45,7 +45,7 @@ RSpec.describe 'Ticket Update', type: :system do
# update should work now # update should work now
find(".edit [name=#{attribute.name}]").select('name 2') find(".edit [name=#{attribute.name}]").select('name 2')
click('.js-attributeBar .js-submit') click('.js-attributeBar .js-submit')
expect(page).to have_no_css('.js-submitDropdown .js-submit[disabled]', wait: 2) expect(page).to have_no_css('.js-submitDropdown .js-submit[disabled]', wait: 10)
end end
ticket.reload ticket.reload
@ -185,7 +185,7 @@ RSpec.describe 'Ticket Update', type: :system do
it 'tickets history of both tickets should show the merge event' do it 'tickets history of both tickets should show the merge event' do
visit "#ticket/zoom/#{origin_ticket.id}" visit "#ticket/zoom/#{origin_ticket.id}"
within(:active_content) do within(:active_content) do
expect(page).to have_css('.js-actions .dropdown-toggle', wait: 3) expect(page).to have_css('.js-actions .dropdown-toggle', wait: 10)
click '.js-actions .dropdown-toggle' click '.js-actions .dropdown-toggle'
click '.js-actions .dropdown-menu [data-type="ticket-history"]' click '.js-actions .dropdown-menu [data-type="ticket-history"]'

View file

@ -112,9 +112,9 @@ RSpec.describe 'Ticket views', type: :system do
release_mouse release_mouse
await_empty_ajax_queue expect do
wait(10, interval: 0.1).until { Ticket.first.articles.last.subject == 'macro note' }
expect(Ticket.first.articles.last.subject).to eq('macro note') end.not_to raise_error
end end
end end
end end
@ -136,12 +136,9 @@ RSpec.describe 'Ticket views', type: :system do
click '.js-submit' click '.js-submit'
end end
await_empty_ajax_queue expect do
wait(10, interval: 0.1).until { [ ticket1.articles.last&.body, ticket2.articles.last&.body ] == [note, note] }
expect([ end.not_to raise_error
ticket1.articles.last&.body,
ticket2.articles.last&.body
]).to be_all note
end end
end end
@ -184,9 +181,9 @@ RSpec.describe 'Ticket views', type: :system do
it 'does basic view test of tickets' do it 'does basic view test of tickets' do
visit 'ticket/view/my_tickets' visit 'ticket/view/my_tickets'
expect(page).to have_text(ticket.title) expect(page).to have_text(ticket.title, wait: 10)
click_on 'My Organization Tickets' click_on 'My Organization Tickets'
expect(page).to have_text(ticket.title) expect(page).to have_text(ticket.title, wait: 10)
end end
end end
end end

View file

@ -448,7 +448,7 @@ RSpec.describe 'Ticket zoom', type: :system do
end end
context 'button is hidden on the go' do context 'button is hidden on the go' do
let(:setting_delete_timeframe) { 5 } let(:setting_delete_timeframe) { 10 }
let(:user) { agent } let(:user) { agent }
let(:item) { 'article_note_self' } let(:item) { 'article_note_self' }
@ -692,8 +692,6 @@ RSpec.describe 'Ticket zoom', type: :system do
encrypt_button = find('.js-securityEncrypt', wait: 5) encrypt_button = find('.js-securityEncrypt', wait: 5)
sign_button = find('.js-securitySign', wait: 5) sign_button = find('.js-securitySign', wait: 5)
await_empty_ajax_queue
active_button_class = '.btn--active' active_button_class = '.btn--active'
expect(encrypt_button.matches_css?(active_button_class, wait: 2)).to be(encrypt) expect(encrypt_button.matches_css?(active_button_class, wait: 2)).to be(encrypt)
expect(sign_button.matches_css?(active_button_class, wait: 2)).to be(sign) expect(sign_button.matches_css?(active_button_class, wait: 2)).to be(sign)
@ -709,8 +707,6 @@ RSpec.describe 'Ticket zoom', type: :system do
within(:active_content) do within(:active_content) do
all('a[data-type=emailReply]').last.click all('a[data-type=emailReply]').last.click
find('.articleNewEdit-body').send_keys('Test') find('.articleNewEdit-body').send_keys('Test')
await_empty_ajax_queue
end end
end end
@ -726,8 +722,6 @@ RSpec.describe 'Ticket zoom', type: :system do
all('a[data-type=emailReply]').last.click all('a[data-type=emailReply]').last.click
find('.articleNewEdit-body').send_keys('Test') find('.articleNewEdit-body').send_keys('Test')
await_empty_ajax_queue
select new_group.name, from: 'group_id' select new_group.name, from: 'group_id'
end end
end end
@ -883,8 +877,6 @@ RSpec.describe 'Ticket zoom', type: :system do
find(:richtext).execute_script "this.innerHTML = \"#{ticket_article_body}\"" find(:richtext).execute_script "this.innerHTML = \"#{ticket_article_body}\""
find('.js-submit').click find('.js-submit').click
end end
await_empty_ajax_queue
end end
def forward def forward
@ -893,8 +885,6 @@ RSpec.describe 'Ticket zoom', type: :system do
fill_in 'To', with: 'customer@example.com' fill_in 'To', with: 'customer@example.com'
find('.js-submit').click find('.js-submit').click
end end
await_empty_ajax_queue
end end
def images_identical?(image_a, image_b) def images_identical?(image_a, image_b)
@ -986,7 +976,7 @@ RSpec.describe 'Ticket zoom', type: :system do
visit "ticket/zoom/#{ticket.id}" visit "ticket/zoom/#{ticket.id}"
refresh # refresh to have assets generated for ticket refresh # refresh to have assets generated for ticket
expect(page).to have_select('state_id', options: %w[new open closed]) expect(page).to have_select('state_id', options: %w[new open closed], wait: 10)
expect(page).to have_no_select('priority_id') expect(page).to have_no_select('priority_id')
expect(page).to have_no_select('owner_id') expect(page).to have_no_select('owner_id')
expect(page).to have_no_css('div.tabsSidebar-tab[data-tab=customer]') expect(page).to have_no_css('div.tabsSidebar-tab[data-tab=customer]')
@ -1119,11 +1109,10 @@ RSpec.describe 'Ticket zoom', type: :system do
# make sure ticket is done loading and change will be pushed via WS # make sure ticket is done loading and change will be pushed via WS
find(:active_ticket_article, ticket_article) find(:active_ticket_article, ticket_article)
await_empty_ajax_queue
ticket_note.update!(internal: false) ticket_note.update!(internal: false)
expect(page).to have_selector(:active_ticket_article, ticket_note) expect(page).to have_selector(:active_ticket_article, ticket_note, wait: 10)
end end
end end
end end
@ -1190,37 +1179,37 @@ RSpec.describe 'Ticket zoom', type: :system do
it 'previous is not clickable for the first item' do it 'previous is not clickable for the first item' do
open_nth_item(0) open_nth_item(0)
expect { click '.pagination .previous' }.not_to change { current_url } expect { click '.pagination .previous' }.not_to change { page.find('.content.active')[:id] }
end end
it 'next is clickable for the first item' do it 'next is clickable for the first item' do
open_nth_item(0) open_nth_item(0)
expect { click '.pagination .next' }.to change { current_url } expect { click '.pagination .next' }.to change { page.find('.content.active')[:id] }
end end
it 'previous is clickable for the middle item' do it 'previous is clickable for the middle item' do
open_nth_item(1) open_nth_item(1)
expect { click '.pagination .previous' }.to change { current_url } expect { click '.pagination .previous' }.to change { page.find('.content.active')[:id] }
end end
it 'next is clickable for the middle item' do it 'next is clickable for the middle item' do
open_nth_item(1) open_nth_item(1)
expect { click '.pagination .next' }.to change { current_url } expect { click '.pagination .next' }.to change { page.find('.content.active')[:id] }
end end
it 'previous is clickable for the last item' do it 'previous is clickable for the last item' do
open_nth_item(2) open_nth_item(2)
expect { click '.pagination .previous' }.to change { current_url } expect { click '.pagination .previous' }.to change { page.find('.content.active')[:id] }
end end
it 'next is not clickable for the last item' do it 'next is not clickable for the last item' do
open_nth_item(2) open_nth_item(2)
expect { click '.pagination .next' }.not_to change { current_url } expect { click '.pagination .next' }.not_to change { page.find('.content.active')[:id] }
end end
def open_nth_item(nth) def open_nth_item(nth)
@ -1243,8 +1232,6 @@ RSpec.describe 'Ticket zoom', type: :system do
visit "ticket/zoom/#{ticket_a.id}" visit "ticket/zoom/#{ticket_a.id}"
await_empty_ajax_queue
visit 'ticket/view/all_unassigned' visit 'ticket/view/all_unassigned'
end end
@ -1252,7 +1239,7 @@ RSpec.describe 'Ticket zoom', type: :system do
within :active_content do within :active_content do
click_on ticket_a.title click_on ticket_a.title
expect(page).to have_css('.pagination-counter') expect(page).to have_css('.pagination-counter', wait: 10)
end end
end end
@ -1262,7 +1249,7 @@ RSpec.describe 'Ticket zoom', type: :system do
visit 'dashboard' visit 'dashboard'
visit "ticket/zoom/#{ticket_a.id}" visit "ticket/zoom/#{ticket_a.id}"
expect(page).to have_css('.pagination-counter') expect(page).to have_css('.pagination-counter', wait: 10)
end end
end end
end end
@ -1293,7 +1280,6 @@ RSpec.describe 'Ticket zoom', type: :system do
# wait for article to be added to the page # wait for article to be added to the page
expect(page).to have_css('.ticket-article-item', count: 1) expect(page).to have_css('.ticket-article-item', count: 1)
await_empty_ajax_queue
# create a on-the-fly article with attachment that will get pushed to open browser # create a on-the-fly article with attachment that will get pushed to open browser
article1 = create(:ticket_article, ticket: ticket) article1 = create(:ticket_article, ticket: ticket)
@ -1310,7 +1296,6 @@ RSpec.describe 'Ticket zoom', type: :system do
# wait for article to be added to the page # wait for article to be added to the page
expect(page).to have_css('.ticket-article-item', count: 2, wait: 10) expect(page).to have_css('.ticket-article-item', count: 2, wait: 10)
await_empty_ajax_queue
# click on forward of created article # click on forward of created article
within :active_ticket_article, article1 do within :active_ticket_article, article1 do
@ -1327,7 +1312,6 @@ RSpec.describe 'Ticket zoom', type: :system do
click '.js-submit' click '.js-submit'
# wait for article to be added to the page # wait for article to be added to the page
await_empty_ajax_queue
expect(page).to have_css('.ticket-article-item', count: 3) expect(page).to have_css('.ticket-article-item', count: 3)
# check if attachment was forwarded successfully # check if attachment was forwarded successfully
@ -1376,7 +1360,6 @@ RSpec.describe 'Ticket zoom', type: :system do
it 'not shown to customer' do it 'not shown to customer' do
visit "ticket/zoom/#{ticket.id}" visit "ticket/zoom/#{ticket.id}"
await_empty_ajax_queue
within :active_content do within :active_content do
expect(page).to have_no_css('.controls[data-name=pending_time]') expect(page).to have_no_css('.controls[data-name=pending_time]')
@ -1389,7 +1372,6 @@ RSpec.describe 'Ticket zoom', type: :system do
ticket.update(pending_time: 1.day.from_now, state: Ticket::State.lookup(name: 'pending reminder')) ticket.update(pending_time: 1.day.from_now, state: Ticket::State.lookup(name: 'pending reminder'))
visit "ticket/zoom/#{ticket.id}" visit "ticket/zoom/#{ticket.id}"
await_empty_ajax_queue
end end
let(:ticket) { Ticket.first } let(:ticket) { Ticket.first }
@ -1436,7 +1418,6 @@ RSpec.describe 'Ticket zoom', type: :system do
ensure_websocket do ensure_websocket do
visit "ticket/zoom/#{ticket.id}" visit "ticket/zoom/#{ticket.id}"
await_empty_ajax_queue
within :active_ticket_article, article do within :active_ticket_article, article do
expect(page).to have_css(%(a[href="#{url}"])) expect(page).to have_css(%(a[href="#{url}"]))
@ -1457,44 +1438,33 @@ RSpec.describe 'Ticket zoom', type: :system do
end end
end end
def check_obscured(top: true, middle: true, bottom: true, scroll_y: 0)
expect(page).to have_text(ticket.title, wait: 10)
wait(5, interval: 0.2).until do
scroll_y != find('.ticketZoom').native.location.y
end
expect(page).to have_css("div#article-content-#{article_at_the_top.id}", obscured: top, wait: 10)
expect(page).to have_css("div#article-content-#{article_in_the_middle.id}", obscured: middle, wait: 10)
expect(page).to have_css("div#article-content-#{article_at_the_bottom.id}", obscured: bottom, wait: 10)
find('.ticketZoom').native.location.y
end
it 'scrolls to given Article ID' do it 'scrolls to given Article ID' do
ensure_websocket do ensure_websocket do
visit "ticket/zoom/#{ticket.id}/#{article_in_the_middle.id}" visit "ticket/zoom/#{ticket.id}"
await_empty_ajax_queue y = check_obscured(bottom: false)
# workaround because browser scrolls in test initially to the bottom
# maybe because the articles are not present?!
refresh
# scroll to article in the middle of the page # scroll to article in the middle of the page
within :active_content do visit "ticket/zoom/#{ticket.id}/#{article_in_the_middle.id}"
find("div#article-content-#{article_in_the_middle.id}").in_fixed_position(wait: 0.5) y = check_obscured(middle: false, scroll_y: y)
expect(find("div#article-content-#{article_at_the_top.id}")).to be_obscured
expect(find("div#article-content-#{article_in_the_middle.id}")).not_to be_obscured
expect(find("div#article-content-#{article_at_the_bottom.id}")).to be_obscured
end
# scroll to article at the top of the page # scroll to article at the top of the page
visit "ticket/zoom/#{ticket.id}/#{article_at_the_top.id}" visit "ticket/zoom/#{ticket.id}/#{article_at_the_top.id}"
await_empty_ajax_queue y = check_obscured(top: false, scroll_y: y)
within :active_content do
find("div#article-content-#{article_in_the_middle.id}").in_fixed_position(wait: 0.5)
expect(find("div#article-content-#{article_at_the_top.id}")).not_to be_obscured
expect(find("div#article-content-#{article_in_the_middle.id}")).to be_obscured
expect(find("div#article-content-#{article_at_the_bottom.id}")).to be_obscured
end
# scroll to article at the bottom of the page # scroll to article at the bottom of the page
visit "ticket/zoom/#{ticket.id}/#{article_at_the_bottom.id}" visit "ticket/zoom/#{ticket.id}/#{article_at_the_bottom.id}"
await_empty_ajax_queue check_obscured(bottom: false, scroll_y: y)
within :active_content do
find("div#article-content-#{article_in_the_middle.id}").in_fixed_position(wait: 0.5)
expect(find("div#article-content-#{article_at_the_top.id}")).to be_obscured
expect(find("div#article-content-#{article_in_the_middle.id}")).to be_obscured
expect(find("div#article-content-#{article_at_the_bottom.id}")).not_to be_obscured
end
end end
end end
end end
@ -1503,12 +1473,11 @@ RSpec.describe 'Ticket zoom', type: :system do
it 'will properly show the "See more" link if you switch between the ticket and the dashboard on new articles' do it 'will properly show the "See more" link if you switch between the ticket and the dashboard on new articles' do
ensure_websocket do ensure_websocket do
visit "ticket/zoom/#{ticket.id}" visit "ticket/zoom/#{ticket.id}"
await_empty_ajax_queue
visit 'dashboard' visit 'dashboard'
expect(page).to have_css("a.js-dashboardMenuItem[data-key='Dashboard'].is-active", wait: 10) expect(page).to have_css("a.js-dashboardMenuItem[data-key='Dashboard'].is-active", wait: 10)
article_id = create(:'ticket/article', ticket: ticket, body: "#{SecureRandom.uuid} #{"lorem ipsum\n" * 200}") article_id = create(:'ticket/article', ticket: ticket, body: "#{SecureRandom.uuid} #{"lorem ipsum\n" * 200}")
expect(page).to have_css('div.tasks a.is-modified', wait: 10) expect(page).to have_css('div.tasks a.is-modified', wait: 30)
visit "ticket/zoom/#{ticket.id}" visit "ticket/zoom/#{ticket.id}"
within :active_content do within :active_content do
@ -1533,7 +1502,6 @@ RSpec.describe 'Ticket zoom', type: :system do
visit "ticket/zoom/#{ticket.id}" visit "ticket/zoom/#{ticket.id}"
find('.js-openDropdownMacro').click find('.js-openDropdownMacro').click
find(:macro, macro.id).click find(:macro, macro.id).click
await_empty_ajax_queue
expect(ticket.reload.articles.last.body).to eq(macro_body) expect(ticket.reload.articles.last.body).to eq(macro_body)
expect(ticket.reload.articles.last.content_type).to eq('text/html') expect(ticket.reload.articles.last.content_type).to eq('text/html')
@ -1598,7 +1566,6 @@ RSpec.describe 'Ticket zoom', type: :system do
click_on 'Link issue' click_on 'Link issue'
fill_in 'link', with: ENV['GITLAB_ISSUE_LINK'] fill_in 'link', with: ENV['GITLAB_ISSUE_LINK']
click_on 'Submit' click_on 'Submit'
await_empty_ajax_queue
# verify issue # verify issue
content = find('.sidebar-git-issue-content') content = find('.sidebar-git-issue-content')
@ -1615,7 +1582,6 @@ RSpec.describe 'Ticket zoom', type: :system do
# delete issue # delete issue
click(".sidebar-git-issue-delete span[data-issue-id='#{ENV['GITLAB_ISSUE_LINK']}']") click(".sidebar-git-issue-delete span[data-issue-id='#{ENV['GITLAB_ISSUE_LINK']}']")
await_empty_ajax_queue
content = find('.sidebar[data-tab=gitlab] .sidebar-content') content = find('.sidebar[data-tab=gitlab] .sidebar-content')
expect(content).to have_text('No linked issues') expect(content).to have_text('No linked issues')
@ -1658,7 +1624,6 @@ RSpec.describe 'Ticket zoom', type: :system do
click_on 'Link issue' click_on 'Link issue'
fill_in 'link', with: ENV['GITHUB_ISSUE_LINK'] fill_in 'link', with: ENV['GITHUB_ISSUE_LINK']
click_on 'Submit' click_on 'Submit'
await_empty_ajax_queue
# verify issue # verify issue
content = find('.sidebar-git-issue-content') content = find('.sidebar-git-issue-content')
@ -1675,7 +1640,6 @@ RSpec.describe 'Ticket zoom', type: :system do
# delete issue # delete issue
click(".sidebar-git-issue-delete span[data-issue-id='#{ENV['GITHUB_ISSUE_LINK']}']") click(".sidebar-git-issue-delete span[data-issue-id='#{ENV['GITHUB_ISSUE_LINK']}']")
await_empty_ajax_queue
content = find('.sidebar[data-tab=github] .sidebar-content') content = find('.sidebar[data-tab=github] .sidebar-content')
expect(content).to have_text('No linked issues') expect(content).to have_text('No linked issues')
@ -1707,7 +1671,6 @@ RSpec.describe 'Ticket zoom', type: :system do
expect(page).to have_text(ticket_open.title, wait: 20) expect(page).to have_text(ticket_open.title, wait: 20)
visit "#ticket/zoom/#{ticket_open.id}" visit "#ticket/zoom/#{ticket_open.id}"
click '.tabsSidebar-tab[data-tab=customer]'
click '.user-tickets[data-type=closed]' click '.user-tickets[data-type=closed]'
expect(page).to have_text(ticket_closed.title, wait: 20) expect(page).to have_text(ticket_closed.title, wait: 20)
end end

View file

@ -159,7 +159,7 @@ class AgentTicketActionLevel0Test < TestCase
css: '.newTicket', css: '.newTicket',
value: 'New Ticket', value: 'New Ticket',
) )
exists_not(css: '.newTicket select[name="group_id"]') exists(css: '.newTicket .form-group.hide select[name="group_id"]')
set( set(
css: '.newTicket input[name="title"]', css: '.newTicket input[name="title"]',

View file

@ -30,14 +30,7 @@ class AgentTicketAttachmentTest < TestCase
sleep 1 sleep 1
# submit form # submit form
click(css: '.content.active .js-submit') click(css: '.content.active .js-submit', expect_alert: true)
sleep 2
# check warning
alert = @browser.switch_to.alert
alert.dismiss()
#alert.accept()
#alert = alert.text
# since selenium webdriver with firefox is not able to upload files, skipp here # since selenium webdriver with firefox is not able to upload files, skipp here
# https://github.com/w3c/webdriver/issues/1230 # https://github.com/w3c/webdriver/issues/1230
@ -90,12 +83,7 @@ class AgentTicketAttachmentTest < TestCase
) )
# submit form # submit form
click(css: '.content.active .js-submit') click(css: '.content.active .js-submit', expect_alert: true)
sleep 2
# check warning
alert = @browser.switch_to.alert
alert.dismiss()
# add attachment, attachment check should quiet # add attachment, attachment check should quiet
file_upload( file_upload(
@ -111,12 +99,6 @@ class AgentTicketAttachmentTest < TestCase
# submit form # submit form
click(css: '.content.active .js-submit') click(css: '.content.active .js-submit')
sleep 2
# no warning
#alert = @browser.switch_to.alert
# check if article exists
# discard changes should gone away # discard changes should gone away
watch_for_disappear( watch_for_disappear(

View file

@ -160,7 +160,12 @@ class AgentTicketMacroTest < TestCase
# when we re-enter the Zoom view for a ticket via the overview # when we re-enter the Zoom view for a ticket via the overview
tasks_close_all() tasks_close_all()
sleep 8 # to update overview list to open correct/next ticket in overview overview_open(
link: '#ticket/view/all_unassigned',
)
await_text(text: ticket1[:title])
await_text(text: ticket2[:title])
ticket_open_by_overview( ticket_open_by_overview(
title: ticket1[:title], title: ticket1[:title],

View file

@ -67,6 +67,9 @@ class AgentTicketOverviewLevel0Test < TestCase
css: %(.content.active table tr td input[value="#{ticket2[:id]}"][type="checkbox"]:checked), css: %(.content.active table tr td input[value="#{ticket2[:id]}"][type="checkbox"]:checked),
) )
# remember current overview count
overview_counter_before = overview_counter()
# select close state & submit # select close state & submit
select( select(
css: '.content.active .bulkAction [name="state_id"]', css: '.content.active .bulkAction [name="state_id"]',
@ -92,6 +95,7 @@ class AgentTicketOverviewLevel0Test < TestCase
) )
# remember current overview count # remember current overview count
await_overview_counter(view: '#ticket/view/all_unassigned', count: overview_counter_before['#ticket/view/all_unassigned'] - 2)
overview_counter_before = overview_counter() overview_counter_before = overview_counter()
# click options and enable number and article count # click options and enable number and article count
@ -188,11 +192,9 @@ class AgentTicketOverviewLevel0Test < TestCase
body: 'overview count test #3', body: 'overview count test #3',
} }
) )
sleep 6
# get new overview count # get new overview count
overview_counter_new = overview_counter() await_overview_counter(view: '#ticket/view/all_unassigned', count: overview_counter_before['#ticket/view/all_unassigned'] + 1)
assert_equal(overview_counter_before['#ticket/view/all_unassigned'] + 1, overview_counter_new['#ticket/view/all_unassigned'])
# open ticket by search # open ticket by search
ticket_open_by_search( ticket_open_by_search(
@ -206,11 +208,9 @@ class AgentTicketOverviewLevel0Test < TestCase
state: 'closed', state: 'closed',
} }
) )
sleep 6
# get current overview count # get current overview count
overview_counter_after = overview_counter() await_overview_counter(view: '#ticket/view/all_unassigned', count: overview_counter_before['#ticket/view/all_unassigned'])
assert_equal(overview_counter_before['#ticket/view/all_unassigned'], overview_counter_after['#ticket/view/all_unassigned'])
# cleanup # cleanup
tasks_close_all() tasks_close_all()
@ -334,8 +334,7 @@ class AgentTicketOverviewLevel0Test < TestCase
) )
# get new overview count # get new overview count
overview_counter_new = overview_counter() await_overview_counter(view: '#ticket/view/all_unassigned', count: overview_counter_before['#ticket/view/all_unassigned'] - 2)
assert_equal(overview_counter_before['#ticket/view/all_unassigned'] - 2, overview_counter_new['#ticket/view/all_unassigned'])
# open ticket by search # open ticket by search
ticket_open_by_search( ticket_open_by_search(
@ -463,8 +462,7 @@ class AgentTicketOverviewLevel0Test < TestCase
) )
# get new overview count # get new overview count
overview_counter_new = overview_counter() await_overview_counter(view: '#ticket/view/all_unassigned', count: overview_counter_before['#ticket/view/all_unassigned'] - 2)
assert_equal(overview_counter_before['#ticket/view/all_unassigned'] - 2, overview_counter_new['#ticket/view/all_unassigned'])
# cleanup # cleanup
tasks_close_all() tasks_close_all()

View file

@ -3,6 +3,20 @@
require 'browser_test_helper' require 'browser_test_helper'
class AgentTicketOverviewTabTest < TestCase class AgentTicketOverviewTabTest < TestCase
def task_count_equals(count)
retries ||= 0
assert_equal(count, @browser.find_elements(css: '.tasks .task').count)
rescue
retries += 1
if retries < 5
sleep 1
retry
end
raise e
end
def test_i def test_i
@browser = browser_instance @browser = browser_instance
login( login(
@ -54,7 +68,7 @@ class AgentTicketOverviewTabTest < TestCase
link: '#ticket/view/all_unassigned', link: '#ticket/view/all_unassigned',
) )
assert_equal(1, @browser.find_elements(css: '.tasks .task').count) task_count_equals(1)
ticket_update( ticket_update(
data: { data: {
@ -70,7 +84,7 @@ class AgentTicketOverviewTabTest < TestCase
timeout: 8, timeout: 8,
) )
assert_equal(1, @browser.find_elements(css: '.tasks .task').count) task_count_equals(1)
ticket_update( ticket_update(
data: { data: {
@ -80,7 +94,7 @@ class AgentTicketOverviewTabTest < TestCase
task_type: 'closeTab', # default: stayOnTab / possible: closeTab, closeNextInOverview, stayOnTab task_type: 'closeTab', # default: stayOnTab / possible: closeTab, closeNextInOverview, stayOnTab
) )
assert_equal(0, @browser.find_elements(css: '.tasks .task').count) task_count_equals(0)
# cleanup # cleanup
tasks_close_all() tasks_close_all()

View file

@ -4,8 +4,9 @@ require 'browser_test_helper'
class AgentUserManageTest < TestCase class AgentUserManageTest < TestCase
def test_agent_customer_ticket_create def test_agent_customer_ticket_create
customer_user_email = "customer-test-#{rand(999_999)}@example.com" random_number = rand(999_999)
firstname = 'Customer Firstname' customer_user_email = "customer-test-#{random_number}@example.com"
firstname = "Customer Firstname #{random_number}"
lastname = 'Customer Lastname' lastname = 'Customer Lastname'
fullname = "#{firstname} #{lastname} <#{customer_user_email}>" fullname = "#{firstname} #{lastname} <#{customer_user_email}>"
@ -21,10 +22,10 @@ class AgentUserManageTest < TestCase
click(css: 'a[href="#new"]', only_if_exists: true) click(css: 'a[href="#new"]', only_if_exists: true)
click(css: 'a[href="#ticket/create"]') click(css: 'a[href="#ticket/create"]')
watch_for( await_text(text: 'New Ticket')
css: '.content.active .newTicket',
timeout: 1, # Rumors say there is a modal reaper which will kill your modals if you dont sleep before a new ticket create
) sleep 3
click(css: '.content.active .newTicket [name="customer_id_completion"]') click(css: '.content.active .newTicket [name="customer_id_completion"]')
@ -77,11 +78,13 @@ class AgentUserManageTest < TestCase
css: '.content.active .newTicket input[name="customer_id_completion"]', css: '.content.active .newTicket input[name="customer_id_completion"]',
value: fullname, value: fullname,
) )
sleep 4
# call new ticket screen again # call new ticket screen again
tasks_close_all() tasks_close_all()
# wait for user get indexed in elastic search
await_global_search(query: random_number)
click(css: 'a[href="#new"]', only_if_exists: true) click(css: 'a[href="#new"]', only_if_exists: true)
click(css: 'a[href="#ticket/create"]') click(css: 'a[href="#ticket/create"]')

View file

@ -162,11 +162,9 @@ class FormTest < TestCase
click( click(
browser: customer, browser: customer,
css: 'body div.zammad-form-modal button[type="submit"]', css: 'body div.zammad-form-modal button[type="submit"]',
expect_alert: true,
) )
# check warning
alert = customer.switch_to.alert
alert.dismiss()
sleep 10 sleep 10
# fill form invalid data - within correct time # fill form invalid data - within correct time

View file

@ -29,6 +29,7 @@ class SwitchToUserTest < TestCase
) )
click( click(
css: '.content.active .icon-switchView', css: '.content.active .icon-switchView',
ajax: false
) )
sleep 3 sleep 3
@ -42,7 +43,7 @@ class SwitchToUserTest < TestCase
) )
login = @browser.find_elements({ css: '.user-menu .user a' })[0].attribute('title') login = @browser.find_elements({ css: '.user-menu .user a' })[0].attribute('title')
assert_equal(login, 'nicole.braun@zammad.org') assert_equal(login, 'nicole.braun@zammad.org')
click(css: '.switchBackToUser .js-close') click(css: '.switchBackToUser .js-close', ajax: false)
sleep 5 sleep 5
login = @browser.find_elements({ css: '.user-menu .user a' })[0].attribute('title') login = @browser.find_elements({ css: '.user-menu .user a' })[0].attribute('title')

View file

@ -542,6 +542,12 @@ class TestCase < ActiveSupport::TestCase
sleep 0.2 if !params[:fast] sleep 0.2 if !params[:fast]
sleep params[:wait] if params[:wait] sleep params[:wait] if params[:wait]
if params[:expect_alert]
check_alert(params)
else
await_empty_ajax_queue(params)
end
end end
=begin =begin
@ -825,6 +831,7 @@ class TestCase < ActiveSupport::TestCase
end end
sleep 0.2 sleep 0.2
await_empty_ajax_queue(params)
end end
=begin =begin
@ -880,6 +887,8 @@ class TestCase < ActiveSupport::TestCase
dropdown.select_by(:text, params[:value]) dropdown.select_by(:text, params[:value])
#puts "select2 - #{params.inspect}" #puts "select2 - #{params.inspect}"
end end
await_empty_ajax_queue(params)
end end
=begin =begin
@ -1265,16 +1274,17 @@ set type of task (closeTab, closeNextInOverview, stayOnTab)
=end =end
def verify_task(params = {}, fallback = false) def verify_task(params = {})
switch_window_focus(params) switch_window_focus(params)
log('verify_task', params) log('verify_task', params)
instance = params[:browser] || @browser instance = params[:browser] || @browser
data = params[:data] data = params[:data]
begin
retries ||= 0
sleep 1 sleep 1
begin
# verify title # verify title
if data[:title] if data[:title]
title = instance.find_elements(css: '.tasks .is-active')[0].text.strip title = instance.find_elements(css: '.tasks .is-active')[0].text.strip
@ -1318,10 +1328,8 @@ set type of task (closeTab, closeNextInOverview, stayOnTab)
end end
end end
rescue => e rescue => e
# just try again retries += 1
if !fallback retry if retries < 5
verify_task(params, true)
end
raise "ERROR: #{e.inspect}" raise "ERROR: #{e.inspect}"
end end
true true
@ -1572,6 +1580,7 @@ wait untill text in selector disabppears
.key_up(:control) .key_up(:control)
.perform .perform
screenshot(browser: instance, comment: 'shortcut_after') screenshot(browser: instance, comment: 'shortcut_after')
await_empty_ajax_queue(params)
end end
=begin =begin
@ -1588,6 +1597,7 @@ wait untill text in selector disabppears
log('window_keys', params) log('window_keys', params)
instance = params[:browser] || @browser instance = params[:browser] || @browser
instance.action.send_keys(params[:value]).perform instance.action.send_keys(params[:value]).perform
await_empty_ajax_queue(params)
end end
=begin =begin
@ -2122,19 +2132,14 @@ wait untill text in selector disabppears
mute_log: true, mute_log: true,
) )
found = false watch_for(
7.times do browser: instance,
element = instance.find_elements(css: '.content.active .newTicket')[0] css: '.content.active .newTicket',
if element timeout: 30,
found = true )
break
end # Rumors say there is a modal reaper which will kill your modals if you dont sleep before a new ticket create
sleep 1 sleep 3
end
if !found
screenshot(browser: instance, comment: 'ticket_create_failed')
raise 'no ticket create screen found!'
end
if data[:group] if data[:group]
if data[:group] == '-NONE-' if data[:group] == '-NONE-'
@ -2570,6 +2575,7 @@ wait untill text in selector disabppears
end end
instance.find_elements(css: '.content.active .js-submit')[0].click instance.find_elements(css: '.content.active .js-submit')[0].click
await_empty_ajax_queue(params)
# do not stay on tab # do not stay on tab
if params[:task_type] == 'closeTab' || params[:task_type] == 'closeNextInOverview' if params[:task_type] == 'closeTab' || params[:task_type] == 'closeNextInOverview'
@ -2867,7 +2873,7 @@ wait untill text in selector disabppears
instance = params[:browser] || @browser instance = params[:browser] || @browser
instance.find_elements(css: '.js-overviewsMenuItem')[0].click instance.find_elements(css: '.js-overviewsMenuItem')[0].click
sleep 2 await_empty_ajax_queue(params)
execute( execute(
browser: instance, browser: instance,
@ -2878,6 +2884,7 @@ wait untill text in selector disabppears
# js: '$(".content.active .overview-header").css("display", "none")', # js: '$(".content.active .overview-header").css("display", "none")',
#) #)
begin
overviews = {} overviews = {}
instance.find_elements(css: '.content.active .sidebar a[href]').each do |element| instance.find_elements(css: '.content.active .sidebar a[href]').each do |element|
url = element.attribute('href') url = element.attribute('href')
@ -2886,10 +2893,19 @@ wait untill text in selector disabppears
#puts url.inspect #puts url.inspect
#puts element.inspect #puts element.inspect
end end
overviews.each_key do |url| overviews.each_key do |url|
count = instance.find_elements(css: ".content.active .sidebar a[href=\"#{url}\"] .badge")[0].text count = instance.find_elements(css: ".content.active .sidebar a[href=\"#{url}\"] .badge")[0].text
overviews[url] = count.to_i overviews[url] = count.to_i
end end
rescue => e
retries ||= 0
retries += 1
sleep 0.5
retry if retries < 5
raise e
end
log('overview_counter', overviews) log('overview_counter', overviews)
overviews overviews
end end
@ -3340,6 +3356,7 @@ wait untill text in selector disabppears
element.send_keys(data[:name]) element.send_keys(data[:name])
instance.find_elements(css: '.modal button.js-submit')[0].click instance.find_elements(css: '.modal button.js-submit')[0].click
await_empty_ajax_queue(params)
modal_disappear( modal_disappear(
browser: instance, browser: instance,
timeout: 5, timeout: 5,
@ -3458,6 +3475,7 @@ wait untill text in selector disabppears
element.clear element.clear
element.send_keys(data[:first_response_time_in_text]) element.send_keys(data[:first_response_time_in_text])
instance.find_elements(css: '.modal button.js-submit')[0].click instance.find_elements(css: '.modal button.js-submit')[0].click
await_empty_ajax_queue(params)
modal_disappear(browser: instance) modal_disappear(browser: instance)
7.times do 7.times do
element = instance.find_elements(css: 'body')[0] element = instance.find_elements(css: 'body')[0]
@ -3661,6 +3679,7 @@ wait untill text in selector disabppears
dropdown.select_by(:text, data[:signature]) dropdown.select_by(:text, data[:signature])
end end
instance.find_elements(css: '.modal button.js-submit')[0].click instance.find_elements(css: '.modal button.js-submit')[0].click
await_empty_ajax_queue(params)
modal_disappear(browser: instance) modal_disappear(browser: instance)
element = instance.find_elements(css: 'body')[0] element = instance.find_elements(css: 'body')[0]
@ -3673,6 +3692,7 @@ wait untill text in selector disabppears
data[:member]&.each do |member| data[:member]&.each do |member|
instance.find_elements(css: 'a[href="#manage"]')[0].click instance.find_elements(css: 'a[href="#manage"]')[0].click
sleep 1 sleep 1
scroll_to(params.merge(css: '.content.active a[href="#manage/users"]'))
instance.find_elements(css: '.content.active a[href="#manage/users"]')[0].click instance.find_elements(css: '.content.active a[href="#manage/users"]')[0].click
sleep 3 sleep 3
element = instance.find_elements(css: '.content.active [name="search"]')[0] element = instance.find_elements(css: '.content.active [name="search"]')[0]
@ -3685,6 +3705,7 @@ wait untill text in selector disabppears
#instance.find_elements(:css => 'label:contains(" ' + action[:name] + '")')[0].click #instance.find_elements(:css => 'label:contains(" ' + action[:name] + '")')[0].click
instance.execute_script(%($(".js-groupList tr:contains(\\"#{data[:name]}\\") .js-groupListItem[value=#{member[:access]}]").prop("checked", true))) instance.execute_script(%($(".js-groupList tr:contains(\\"#{data[:name]}\\") .js-groupListItem[value=#{member[:access]}]").prop("checked", true)))
instance.find_elements(css: '.modal button.js-submit')[0].click instance.find_elements(css: '.modal button.js-submit')[0].click
await_empty_ajax_queue(params)
modal_disappear(browser: instance) modal_disappear(browser: instance)
end end
end end
@ -3933,6 +3954,8 @@ wait untill text in selector disabppears
css: '.content.active a[href="#manage/roles"]', css: '.content.active a[href="#manage/roles"]',
mute_log: true, mute_log: true,
) )
await_text(container: '.content.active table tr td', text: data[:name])
instance.execute_script(%($('.content.active table tr td:contains(" #{data[:name]}")').first().click())) instance.execute_script(%($('.content.active table tr td:contains(" #{data[:name]}")').first().click()))
modal_ready(browser: instance) modal_ready(browser: instance)
@ -4830,4 +4853,124 @@ wait untill text in selector disabppears
screenshot(browser: instance, comment: "object_manager_attribute_#{action}_failed") screenshot(browser: instance, comment: "object_manager_attribute_#{action}_failed")
raise "object_manager_attribute_#{action}_failed" raise "object_manager_attribute_#{action}_failed"
end end
def check_alert(params = {})
instance = params[:browser] || @browser
tries = 5
begin
alert = instance.switch_to.alert
alert.dismiss()
rescue e
tries -= 1
sleep 0.5
retry if tries.positive?
raise e
end
end
=begin
This function waits for ajax requests and object form flow to be done
await_empty_ajax_queue
=end
def await_empty_ajax_queue(params = {})
return if params[:ajax] == false
instance = params[:browser] || @browser
10.times do
sleep 0.5
break if instance.execute_script('return typeof(App) === "undefined"')
break if instance.execute_script('return App.Ajax.queue().length').zero?
end
end
=begin
This function waits for a text to be ready in the dom. By default it searches in the active content.
await_text(text: 'New Ticket')
await_text(text: 'New Ticket', container: 'body')
=end
def await_text(params)
return if params[:ajax] == false
instance = params[:browser] || @browser
container = '.content.active'
if params[:container]
container = params[:container]
end
20.times do
log('await_text', params)
break if instance.execute_script("return $(\"#{container}:contains('#{params[:text]}')\").length").positive?
sleep 0.5
end
end
=begin
This function waits for the overview_counter to return a specific result.
await_overview_counter(view: '#ticket/view/all_unassigned', count: overview_counter_before['#ticket/view/all_unassigned'] - 2)
=end
def await_overview_counter(params)
result = nil
40.times do
result = overview_counter
if result[ params[:view] ] != params[:count]
sleep 0.5
next
end
break
end
assert_equal(params[:count], result[ params[:view] ])
end
=begin
This function waits for a search result to be available in the global search.
It can help to verify if a user is indexed in elastic search.
await_global_search(query: 'customer 1 firstname')
=end
def await_global_search(params)
instance = params[:browser] || @browser
30.times do
log('await_global_search', params)
set(
css: 'input#global-search',
value: params[:query],
)
break if instance.execute_script("return $(\"ul.global-search-result:visible:contains('#{params[:query]}')\").length") == 1
sleep 0.5
end
set(
css: 'input#global-search',
value: '',
)
end
end end