From a1d1587a3c55ce402b94b61cf4f036864679b862 Mon Sep 17 00:00:00 2001 From: Victor Grousset/tuxayo Date: Mon, 29 Jan 2024 20:06:04 +0100 Subject: [PATCH] Bug 35506: additional hardening of selenium/regressions.t For "Encoding in session variables" and "Display circulation table correctly" Using wait_for_ajax. And a manual refresh of the page. And make wait_for_ajax display a stack trace and take a screenshot when timeout. And make wait_for_ajax taking an optional param for the number of retries. --- t/db_dependent/selenium/regressions.t | 13 +++++++++- t/lib/Selenium.pm | 35 +++++++++++++++++++-------- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/t/db_dependent/selenium/regressions.t b/t/db_dependent/selenium/regressions.t index b9e9cb2edf..349dcf4f69 100755 --- a/t/db_dependent/selenium/regressions.t +++ b/t/db_dependent/selenium/regressions.t @@ -189,6 +189,9 @@ subtest 'Display circulation table correctly' => sub { # Display the table clicking on the "Show checkouts" button $driver->find_element('//a[@id="issues-table-load-now-button"]')->click; + # Wait for the checkouts table to load + $s->wait_for_ajax; + my @thead_th = $driver->find_elements('//table[@id="issues-table"]/thead/tr/th'); my $thead_length = 0; $thead_length += $_->get_attribute('colspan', 1) || 0 for @thead_th; @@ -313,14 +316,22 @@ subtest 'Encoding in session variables' => sub { $driver->find_element('//input[@id="barcode"]')->send_keys( $item->barcode ); $driver->find_element('//fieldset[@id="circ_circulation_issue"]/button[@type="submit"]')->click; + # For some crazy reason it's not reliable to wait for the page to + # refresh. It can get stuck (seen in failure screenshot). Even if + # the logs show that a page was returned to the browser. The + # checkout is made so going directly again to the page works. + $driver->get( $base_url . "/circ/circulation.pl?borrowernumber=" . $patron->borrowernumber ); + # Display the table clicking on the "Show checkouts" button $driver->find_element('//a[@id="issues-table-load-now-button"]') ->click; + # Wait for the checkouts table to load + $s->wait_for_ajax; my @tds = $driver->find_elements( '//table[@id="issues-table"]/tbody/tr[2]/td'); - # Select the td for "Checked out from" (FIXME this is not robust and could be improved + # Select the td for "Checked out from" my $td_checked_out_from = $tds[8]; is( $td_checked_out_from->get_text(), diff --git a/t/lib/Selenium.pm b/t/lib/Selenium.pm index 99bc68f1db..4b9e1b1ca6 100644 --- a/t/lib/Selenium.pm +++ b/t/lib/Selenium.pm @@ -56,12 +56,7 @@ sub add_error_handler { $self->{driver}->error_handler( sub { my ( $driver, $selenium_error ) = @_; - print STDERR "\nSTRACE:"; - my $i = 1; - while ( (my @call_details = (caller($i++))) ){ - print STDERR "\t" . $call_details[1]. ":" . $call_details[2] . " in " . $call_details[3]."\n"; - } - print STDERR "\n"; + $self->_print_stack_trace; $self->capture( $driver ); $driver->quit(); croak $selenium_error; @@ -194,17 +189,22 @@ sub wait_for_element_visible { } sub wait_for_ajax { - my ( $self ) = @_; + my ( $self, $max_retries ) = @_; my $is_ready; - my $max_retries = $self->max_retries; + $max_retries ||= $self->max_retries; my $i; + $is_ready = $self->driver->execute_script('return jQuery.active == 0'); while ( not $is_ready ) { $is_ready = $self->driver->execute_script('return jQuery.active == 0'); $self->driver->pause(1000) unless $is_ready; - die "Cannot wait more for jQuery to be active (wait_for_ajax)" - if $max_retries <= ++$i + if ( $max_retries <= ++$i ) { + $self->capture( $self->driver ); + $self->_print_stack_trace; + $self->driver->quit(); + die "Cannot wait more for jQuery to be active (wait_for_ajax)"; + } } } @@ -267,6 +267,16 @@ sub click_when_visible { sub max_retries { 10 } +sub _print_stack_trace { + print STDERR "\nSTRACE:"; + my $i = 1; + while ( ( my @call_details = ( caller( $i++ ) ) ) ) { + print STDERR "\t" . $call_details[1] . ":" . $call_details[2] . " in " . $call_details[3] . "\n"; + } + print STDERR "\n"; +} + + =head1 NAME t::lib::Selenium - Selenium helper module @@ -358,6 +368,11 @@ It will remove any kinds of error raised by the driver. It can be useful in some cases, for instance if you want to make sure something will not happen and that could make the driver exploses otherwise. You certainly should call it for only one statement then must call add_error_handler right after. +=head2 wait_for_ajax + + Wait until all XHR requests are finished. Timeouts after + $self->max_retries attempts. (ajustable by optional argument) + =head1 AUTHORS Jonathan Druart -- 2.43.0