diff --git a/t/db_dependent/selenium/administration_tasks.t b/t/db_dependent/selenium/administration_tasks.t index 08c5a38..160395b 100644 --- a/t/db_dependent/selenium/administration_tasks.t +++ b/t/db_dependent/selenium/administration_tasks.t @@ -30,6 +30,7 @@ use C4::Biblio qw( AddBiblio ); # We shouldn't use it use Test::More tests => 1; use MARC::Record; use MARC::Field; +use t::lib::Selenium; my $dbh = C4::Context->dbh; my $login = 'koha'; @@ -37,6 +38,7 @@ my $password = 'koha'; my $base_url= 'http://'.C4::Context->preference("staffClientBaseURL")."/cgi-bin/koha/"; my $opac_url= C4::Context->preference("OPACBaseURL"); +my $number_of_biblios_to_insert = 0; our $sample_data = { category => { categorycode => 'test_cat', @@ -71,28 +73,31 @@ SKIP: { $prev_time = $start; $driver->get($base_url."mainpage.pl"); like( $driver->get_title(), qr(Log in to Koha), ); - auth( $driver, $login, $password ); - time_diff("main"); + t::lib::Selenium::auth( $driver, $login, $password ); + t::lib::Selenium::time_diff($prev_time, "main"); # Navigate to the Administration area and create an item type - $driver->find_element_by_xpath('/html/body/div[4]/div/div[1]/div/div[1]/div[2]/div/ul/li[5]/a')->click; + $driver->find_element('//a[@href="/cgi-bin/koha/admin/admin-home.pl"]')->click; +# t::lib::Selenium::pause_driver($driver, '/html/body/div[4]/div/div/div[2]/div[1]/dl[1]/dt[2]/a'); +# $driver->pause(20000); $driver->pause(20000); - $driver->find_element_by_xpath('/html/body/div[4]/div/div/div[2]/div[1]/dl[1]/dt[2]/a')->click; +# $driver->find_element_by_xpath('/html/body/div[4]/div/div/div[2]/div[1]/dl[1]/dt[2]/a')->click; +# $$driver->find_element_by_xpath('/html/body/div[4]/div/div/div[2]/div[1]/dl[1]/dt[2]/a')->click; $driver->pause(20000); $driver->find_element('//a[@id="newitemtype"]')->click; $driver->pause(20000); - $driver->find_element_by_xpath('/html/body/div[4]/div/div[1]/div/form/fieldset[1]/ol[1]/li[1]/input')->send_keys("DVD"); - $driver->find_element_by_xpath('/html/body/div[4]/div/div[1]/div/form/fieldset[1]/ol[1]/li[2]/input')->send_keys("Digital Optical Disc"); + $driver->find_element('//input[@id="itemtype"]')->send_keys("DVD"); + $driver->find_element('//input[@id="description"]')->send_keys("Digital Optical Disc"); $driver->find_element_by_xpath('/html/body/div[4]/div/div[1]/div/form/fieldset[2]/input')->click; if ( $driver->find_element('//a[@href="/cgi-bin/koha/admin/itemtypes.pl?op=add_form&itemtype=DVD"]')) { - time_diff("Item type successfully added"); + t::lib::Selenium::time_diff($prev_time, "Item type successfully added"); } else { - time_diff("Item type not added successfully"); + t::lib::Selenium::time_diff($prev_time, "Item type not added successfully"); } # Add circulation/fine rules $driver->pause(20000); - $driver->find_element_by_xpath('/html/body/div[3]/a[2]')->click; + $driver->find_element('//input[@href="/cgi-bin/koha/admin/admin-home.pl"]')->click; $driver->pause(20000); $driver->find_element_by_xpath('/html/body/div[4]/div/div/div[2]/div[1]/dl[2]/dt[2]/a')->click; $driver->pause(20000); @@ -103,7 +108,7 @@ SKIP: { $driver->find_element_by_xpath('/html/body/div[4]/div/div[1]/div/div[2]/form[3]/table/tbody/tr[2]/td[22]/input')->send_keys("4"); $driver->find_element_by_xpath('/html/body/div[4]/div/div[1]/div/div[2]/form[3]/table/tbody/tr[2]/td[23]/input')->send_keys("4"); $driver->find_element_by_xpath('/html/body/div[4]/div/div[1]/div/div[2]/form[3]/table/tbody/tr[2]/td[28]/button[1]')->click; - time_diff("Circulation rule added"); + t::lib::Selenium::time_diff($prev_time, "Circulation rule added"); # Modify frameworks $driver->pause(20000); @@ -111,7 +116,6 @@ SKIP: { $driver->pause(20000); $driver->find_element_by_xpath('/html/body/div[4]/div/div/div[2]/div[2]/dl[1]/dt[1]/a')->click; $driver->pause(20000); - warn $driver->get_title(); $driver->find_element_by_xpath('/html/body/div[4]/div/div[1]/div/div[2]/table/tbody/tr[5]/td[3]/div/a')->click; $driver->find_element_by_xpath('/html/body/div[4]/div/div[1]/div/div[2]/table/tbody/tr[5]/td[3]/div/ul/li[1]/a')->click; $driver->pause(20000); @@ -128,7 +132,7 @@ SKIP: { $driver->find_element_by_xpath('/html/body/div[4]/div/div[1]/div/form/fieldset[1]/ol/li[3]/input')->send_keys("Local Dewey"); $driver->find_element_by_xpath('/html/body/div[4]/div/div[1]/div/form/fieldset[2]/input')->click; $driver->pause(20000); - time_diff("Added subfield to framework"); + t::lib::Selenium::time_diff($prev_time, "Added subfield to framework"); #Add library $driver->get_title(); @@ -147,9 +151,9 @@ SKIP: { $driver->find_element_by_xpath('/html/body/div[4]/div/div[1]/div/div[3]/div[1]/div[2]/label/select')->click; $driver->find_element_by_xpath('/html/body/div[4]/div/div[1]/div/div[3]/div[1]/div[2]/label/select/option[3]')->click; if ($driver->find_element('//td[text()="Test library"]')) { - time_diff("Library successfully added"); + t::lib::Selenium::time_diff($prev_time, "Library successfully added"); } else { - time_diff("Library not successfully added"); + t::lib::Selenium::time_diff($prev_time, "Library not successfully added"); } @@ -168,9 +172,9 @@ SKIP: { $driver->find_element_by_xpath('/html/body/div[4]/div/div[1]/div/form/fieldset[1]/ol/li[4]/input')->send_keys("Hardcover"); $driver->find_element_by_xpath('/html/body/div[4]/div/div[1]/div/form/fieldset[2]/input[2]')->click; if ($driver->find_element('//td[text()="HBK"]')) { - time_diff("Authorised value successfully added"); + t::lib::Selenium::time_diff($prev_time, "Authorised value successfully added"); } else { - time_diff("Authorised value not successfully added"); + t::lib::Seleniumtime_diff($prev_time, "Authorised value not successfully added"); } #Patron category @@ -188,9 +192,9 @@ SKIP: { $driver->find_element_by_xpath('/html/body/div[4]/div/div[1]/div/form/fieldset[2]/input')->click; $driver->pause(20000); if ($driver->find_element('//td[text()="AD"]')) { - time_diff("Patron category successfully added"); + t::lib::Selenium::time_diff($prev_time, "Patron category successfully added"); } else { - time_diff("Patron category not successfully added"); + t::lib::Selenium::time_diff(i$prev_time, "Patron category not successfully added"); } #Add patron attribute type @@ -206,11 +210,10 @@ SKIP: { $driver->find_element_by_xpath('/html/body/div[4]/div/div[1]/div/form/fieldset[1]/ol/li[11]/select/option[2]')->click; $driver->find_element_by_xpath('/html/body/div[4]/div/div[1]/div/form/fieldset[2]/input')->click; $driver->pause(20000); - warn $driver->get_title(); if ($driver->find_element('//td[text()="DL"]')) { - time_diff("Patron attribute type successfully added"); + t::lib::Selenium::time_diff($prev_time, "Patron attribute type successfully added"); } else { - time_diff("Patron attribute type not successfully added"); + t::lib::Selenium::time_diff($prev_time, "Patron attribute type not successfully added"); } #Add Z39.50 target server @@ -229,9 +232,9 @@ SKIP: { $driver->find_element_by_xpath('/html/body/div[4]/div/div[1]/div/form/fieldset[2]/input')->click; $driver->pause(20000); if ($driver->find_element('//td[text()="consull.ull.ac.uk:210"]')) { - time_diff("Z39.50 target successfully added"); + t::lib::Selenium::time_diff($prev_time, "Z39.50 target successfully added"); } else { - time_diff("Z39.50 target not successfully added"); + t::lib::Selenium::time_diff($prev_time, "Z39.50 target not successfully added"); } #Add item circulation alerts @@ -240,7 +243,7 @@ SKIP: { $driver->find_element_by_xpath('/html/body/div[4]/div/div/div[2]/div[1]/dl[2]/dt[6]/a')->click; $driver->pause(20000); $driver->find_element_by_xpath('/html/body/div[4]/div/div[1]/div/div[2]/div[1]/table/tbody/tr[1]/td[1]')->click; - time_diff("Added item circulation alert"); + t::lib::Selenium::time_diff($prev_time, "Added item circulation alert"); #Add city $driver->find_element_by_xpath('/html/body/div[3]/a[2]')->click; @@ -255,9 +258,9 @@ SKIP: { $driver->find_element_by_xpath('/html/body/div[4]/div/div[1]/div/form/fieldset[2]/input')->click; $driver->pause(20000); if ($driver->find_element('//td[text()="Wellington"]')) { - time_diff("City successfully added"); + t::lib::Selenium::time_diff($prev_time, "City successfully added"); } else { - time_diff("City not successfully added"); + t::lib::Selenium::time_diff($prev_time, "City not successfully added"); } close $fh; @@ -265,52 +268,6 @@ SKIP: { }; END { - cleanup() if $cleanup_needed; + t::lib::Selenium::cleanup($sample_data,$number_of_biblios_to_insert,$borrowernumber) if $cleanup_needed; }; -sub auth { - my ( $driver, $login, $password) = @_; - fill_form( $driver, { userid => 'koha', password => 'koha' } ); - my $login_button = $driver->find_element('//input[@id="submit"]'); - $login_button->submit(); -} - -sub patron_auth { - my ( $driver,$patronusername, $patronpassword) = @_; - fill_form( $driver, { userid => $patronusername, password => $patronpassword } ); - my $login_button = $driver->find_element('//input[@id="submit"]'); - $login_button->submit(); -} - -sub patron_opac_auth { - my ( $driver,$patronusername, $patronpassword) = @_; - fill_form( $driver, { userid => $patronusername, password => $patronpassword } ); - my $login_button = $driver->find_element('//input[@value="Log in"]'); - $login_button->submit(); -} - -sub fill_form { - my ( $driver, $values ) = @_; - while ( my ( $id, $value ) = each %$values ) { - my $element = $driver->find_element('//*[@id="'.$id.'"]'); - my $tag = $element->get_tag_name(); - if ( $tag eq 'input' ) { - $driver->find_element('//input[@id="'.$id.'"]')->send_keys($value); - } elsif ( $tag eq 'select' ) { - $driver->find_element('//select[@id="'.$id.'"]/option[@value="'.$value.'"]')->click; - } - } -} - -sub cleanup { - my $dbh = C4::Context->dbh; - $dbh->do(q|DELETE FROM categories WHERE categorycode = ?|, {}, $sample_data->{category}{categorycode}); - $dbh->do(q|DELETE FROM borrowers WHERE userid = ?|, {}, $sample_data->{patron}{userid}); -} - -sub time_diff { - my $lib = shift; - my $now = gettimeofday; - warn "CP $lib = " . sprintf("%.2f", $now - $prev_time ) . "\n"; - $prev_time = $now; -} diff --git a/t/lib/Selenium.pm b/t/lib/Selenium.pm new file mode 100644 index 0000000..9e05e70 --- /dev/null +++ b/t/lib/Selenium.pm @@ -0,0 +1,185 @@ +package t::lib::Selenium; + +use Modern::Perl; + +use Koha::Database; + +use Carp; +use Module::Load; +use String::Random; +use Time::HiRes qw(gettimeofday); +use Selenium::Waiter qw/wait_until/; +use Try::Tiny; + +my $dbh = C4::Context->dbh; +my $login = 'koha'; +my $password = 'koha'; +my $base_url= 'http://'.C4::Context->preference("staffClientBaseURL")."/cgi-bin/koha/"; + +sub auth { + my ( $driver, $login, $password) = @_; + fill_form( $driver, { userid => 'koha', password => 'koha' } ); + my $login_button = $driver->find_element('//input[@id="submit"]'); + $login_button->submit(); +} + +sub patron_auth { + my ( $driver,$patronusername, $patronpassword) = @_; + fill_form( $driver, { userid => $patronusername, password => $patronpassword } ); + my $login_button = $driver->find_element('//input[@id="submit"]'); + $login_button->submit(); +} + +sub patron_opac_auth { + my ( $driver,$patronusername, $patronpassword) = @_; + fill_form( $driver, { userid => $patronusername, password => $patronpassword } ); + my $login_button = $driver->find_element('//input[@value="Log in"]'); + $login_button->submit(); +} + +sub fill_form { + my ( $driver, $values ) = @_; + while ( my ( $id, $value ) = each %$values ) { + my $element = $driver->find_element('//*[@id="'.$id.'"]'); + my $tag = $element->get_tag_name(); + if ( $tag eq 'input' ) { + $driver->find_element('//input[@id="'.$id.'"]')->send_keys($value); + } elsif ( $tag eq 'select' ) { + $driver->find_element('//select[@id="'.$id.'"]/option[@value="'.$value.'"]')->click; + } + } +} + +sub cleanup { + my ($sample_data, $number_of_biblios_to_insert,$borrowernumber) = @_; + my $dbh = C4::Context->dbh; + $dbh->do(q|DELETE FROM categories WHERE categorycode = ?|, {}, $sample_data->{category}{categorycode}); + $dbh->do(q|DELETE FROM borrowers WHERE userid = ?|, {}, $sample_data->{patron}{userid}); + for my $i ( 1 .. $number_of_biblios_to_insert ) { + $dbh->do(qq|DELETE FROM biblio WHERE title = "test biblio $i"|); + }; + + $dbh->do(q|DELETE FROM issues where borrowernumber=?|, {}, $borrowernumber); + $dbh->do(q|DELETE FROM old_issues where borrowernumber=?|, {},$borrowernumber); + for my $i ( 1 .. $number_of_biblios_to_insert ) { + $dbh->do(qq|DELETE items, biblio FROM biblio INNER JOIN items ON biblio.biblionumber = items.biblionumber WHERE biblio.title ="test biblio$i"|); + }; +} + +sub time_diff { + my ($prev_time, $lib) = (@_); + my $now = gettimeofday; + warn "CP $lib = " . sprintf("%.2f", $now - $prev_time ) . "\n"; + $prev_time = $now; +} + +sub pause_driver { + my ($driver, $element) = @_; + $driver->set_implicit_wait_timeout(30000); + my $elem_exists = wait_until {$driver->find_element_by_xpath('$element')}; + + if ($elem_exists) { + $driver->find_element_by_xpath('$element')->click; + } +} + + +=head1 NAME + +t::lib::Selenium.pm - Koha module for common Selenium functions + +=head1 SYNOPSIS + + +=head1 DESCRIPTION + +This Perl module + + +This module automatically creates database records for you. +If needed, records for foreign keys are created too. +Values will be randomly generated if not passed to TestBuilder. +Note that you should wrap these actions in a transaction yourself. + +=head1 METHODS + +=head2 new + + my $builder = t::lib::TestBuilder->new; + + Constructor - Returns the object TestBuilder + +=head2 schema + + my $schema = $builder->schema; + + Getter - Returns the schema of DBIx::Class + +=head2 delete + + $builder->delete({ + source => $source, + records => $patron, # OR: records => [ $patron, ... ], + }); + + Delete individual records, created by builder. + Returns the number of delete attempts, or undef. + +=head2 build + + $builder->build({ source => $source_name, value => $value }); + + Create a test record in the table, represented by $source_name. + The name is required and must conform to the DBIx::Class schema. + Values may be specified by the optional $value hashref. Will be + randomized otherwise. + If needed, TestBuilder creates linked records for foreign keys. + Returns the values of the new record as a hashref, or undef if + the record could not be created. + + Note that build also supports recursive hash references inside the + value hash for foreign key columns, like: + value => { + column1 => 'some_value', + fk_col2 => { + columnA => 'another_value', + } + } + The hash for fk_col2 here means: create a linked record with build + where columnA has this value. In case of a composite FK the hashes + are merged. + + Realize that passing primary key values to build may result in undef + if a record with that primary key already exists. + +=head2 build_object + +Given a plural Koha::Object-derived class, it creates a random element, and +returns the corresponding Koha::Object. + + my $patron = $builder->build_object({ class => 'Koha::Patrons' [, value => { ... }] }); + +=head1 AUTHOR + +Alex Buckley + +Catalyst Koha Development Team + +=head1 COPYRIGHT + +Copyright 2017 - Catalyst IT + +=head1 LICENSE + +This file is part of Koha. + +Koha 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 3 of the License, or (at your option) any later version. + +Koha 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 Koha; if not, see . + +=cut + +1;