Bug 26384: Fix executable flags
[koha.git] / t / db_dependent / selenium / basic_workflow.t
1 #!/usr/bin/perl
2
3 # This file is part of Koha.
4 #
5 # Koha is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # Koha is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18
19
20 # wget https://selenium-release.storage.googleapis.com/2.53/selenium-server-standalone-2.53.1.jar # Does not work with 3.4, did not test the ones between
21 # sudo apt-get install xvfb firefox-esr
22 # SELENIUM_PATH=/home/vagrant/selenium-server-standalone-2.53.1.jar
23 # Xvfb :1 -screen 0 1024x768x24 2>&1 >/dev/null &
24 # DISPLAY=:1 java -jar $SELENIUM_PATH
25 #
26 # Then you can execute the test file.
27 #
28 # If you get:
29 # Wide character in print at /usr/local/share/perl/5.20.2/Test2/Formatter/TAP.pm line 105.
30 # #                   'Koha › Patrons › Add patron test_patron_surname (Adult)'
31 # #     doesn't match '(?^u:Patron details for test_patron_surname)'
32 #
33 # Ignore and retry (FIXME LATER...)
34
35 use Modern::Perl;
36
37 use Time::HiRes qw(gettimeofday);
38 use POSIX qw(strftime);
39 use C4::Context;
40 use C4::Biblio qw( AddBiblio ); # We shouldn't use it
41
42 use Koha::CirculationRules;
43
44 use Test::More tests => 22;
45 use MARC::Record;
46 use MARC::Field;
47
48 use t::lib::Selenium;
49
50 my $dbh      = C4::Context->dbh;
51
52 my $number_of_biblios_to_insert = 3;
53 our $sample_data = {
54     category => {
55         categorycode    => 'TEST_CAT',
56         description     => 'test cat description',
57         enrolmentperiod => '12',
58         category_type   => 'A'
59     },
60     patron => {
61         surname    => 'test_patron_surname',
62         cardnumber => '4242424242',
63         userid     => 'test_username',
64         password   => '1BetterPassword',
65         password2  => '1BetterPassword'
66     },
67     itemtype => {
68         itemtype     => 'IT4TEST',
69         description  => 'Just an itemtype for tests',
70         rentalcharge => 0,
71         notforloan   => 0,
72     },
73     issuingrule => {
74         categorycode  => 'test_cat',
75         itemtype      => 'IT4test',
76         branchcode    => undef,
77         maxissueqty   => '5',
78         issuelength   => '5',
79         lengthunit    => 'days',
80         renewalperiod => '5',
81         reservesallowed => '5',
82         onshelfholds  => '1',
83         opacitemholds => 'Y',
84       },
85 };
86 our ( $borrowernumber, $start, $prev_time, $cleanup_needed );
87
88 $dbh->do(q|INSERT INTO itemtypes(itemtype) VALUES (?)|, undef, $sample_data->{itemtype}{itemtype});
89
90 SKIP: {
91     eval { require Selenium::Remote::Driver; };
92     skip "Selenium::Remote::Driver is needed for selenium tests.", 22 if $@;
93
94     $cleanup_needed = 1;
95
96     open my $fh, '>>', '/tmp/output.txt';
97
98     my $s = t::lib::Selenium->new;
99
100     my $driver = $s->driver;
101     my $base_url = $s->base_url;
102
103     $start = gettimeofday;
104     $prev_time = $start;
105     $driver->get($base_url."mainpage.pl");
106     like( $driver->get_title(), qr(Log in to Koha), );
107     $s->auth;
108     time_diff("main");
109
110     $driver->get($base_url.'admin/categories.pl');
111     like( $driver->get_title(), qr(Patron categories), );
112     $driver->find_element('//a[@id="newcategory"]')->click;
113     like( $driver->get_title(), qr(New category), );
114     $s->fill_form( $sample_data->{category} );
115     $driver->find_element('//fieldset[@class="action"]/input[@type="submit"]')->click;
116
117     time_diff("add patron category");
118     $driver->get($base_url.'/members/memberentry.pl?op=add&amp;categorycode='.$sample_data->{category}{categorycode});
119     like( $driver->get_title(), qr(Add .*$sample_data->{category}{description}), );
120     $s->fill_form( $sample_data->{patron} );
121     $driver->find_element('//button[@id="saverecord"]')->click;
122     like( $driver->get_title(), qr(Patron details for $sample_data->{patron}{surname}), );
123
124     ####$driver->get($base_url.'/members/members-home.pl');
125     ####fill_form( $driver, { searchmember => $sample_data->{patron}{cardnumber} } );
126     ####$driver->find_element('//div[@id="header_search"]/div/form/input[@type="submit"]')->click;
127     ####like( $driver->get_title(), qr(Patron details for), );
128
129     time_diff("add patron");
130
131     $borrowernumber = $dbh->selectcol_arrayref(q|SELECT borrowernumber FROM borrowers WHERE userid=?|, {}, $sample_data->{patron}{userid} )->[0];
132
133     my @biblionumbers;
134     for my $i ( 1 .. $number_of_biblios_to_insert ) {
135         my $biblio = MARC::Record->new();
136         my $title = 'test biblio '.$i;
137         if ( C4::Context->preference('marcflavour') eq 'UNIMARC' ) {
138             $biblio->append_fields(
139                 MARC::Field->new('200', ' ', ' ', a => 'test biblio '.$i),
140                 MARC::Field->new('200', ' ', ' ', f => 'test author '.$i),
141             );
142         } else {
143             $biblio->append_fields(
144                 MARC::Field->new('245', ' ', ' ', a => 'test biblio '.$i),
145                 MARC::Field->new('100', ' ', ' ', a => 'test author '.$i),
146             );
147         }
148         my ($biblionumber, $biblioitemnumber) = AddBiblio($biblio, '');
149         push @biblionumbers, $biblionumber;
150     }
151
152     time_diff("add biblio");
153
154     my $itemtype = $sample_data->{itemtype};
155
156     my $issuing_rules = $sample_data->{issuingrule};
157     Koha::CirculationRules->set_rules(
158         {
159             categorycode => $issuing_rules->{categorycode},
160             itemtype     => $issuing_rules->{itemtype},
161             branchcode   => $issuing_rules->{branchcode},
162             rules => {
163                 maxissueqty     => $issuing_rules->{maxissueqty},
164                 issuelength     => $issuing_rules->{issuelength},
165                 lengthunit      => $issuing_rules->{lengthunit},
166                 renewalperiod   => $issuing_rules->{renewalperiod},
167                 reservesallowed => $issuing_rules->{reservesallowed},
168                 onshelfholds    => $issuing_rules->{onshelfholds},
169                 opacitemholds   => $issuing_rules->{opacitemholds},
170
171               }
172         }
173     );
174
175
176     for my $biblionumber ( @biblionumbers ) {
177         $driver->get($base_url."/cataloguing/additem.pl?biblionumber=$biblionumber");
178         like( $driver->get_title(), qr(test biblio \d+ by test author), );
179         my $form = $driver->find_element('//form[@name="f"]');
180         my $inputs = $driver->find_child_elements($form, '//input[@type="text"]');
181         for my $input ( @$inputs ) {
182             next if $input->is_hidden();
183
184             my $id = $input->get_attribute('id');
185             next unless $id =~ m|^tag_952_subfield|;
186
187             my $v;
188
189             # FIXME This is based on default values
190             if (   $id =~ m|^tag_952_subfield_g|   # price
191                 or $id =~ m|^tag_952_subfield_v| ) # replacementprice
192             {
193                 $v = '42';    # It's a price
194             }
195             elsif (
196                 $id =~ m|^tag_952_subfield_f| #tag_952_subfield_g
197             ) {
198                 # It's a varchar(10)
199                 $v = 't_value_x';
200             }
201             elsif (
202                 $id =~ m|^tag_952_subfield_w| # replacementpricedate
203             ) {
204                 $v = strftime("%Y-%m-%d", localtime);
205             }
206             elsif (
207                 $id =~ m|^tag_952_subfield_d| # dateaccessioned
208             ) {
209                 $v = ""; # The input has been prefilled with %Y-%m-%d already
210             }
211             else {
212                 $v = 't_value_bib' . $biblionumber;
213             }
214             $input->send_keys( $v );
215         }
216
217         $driver->find_element('//input[@name="add_submit"]')->click;
218         like( $driver->get_title(), qr($biblionumber.*Items) );
219
220         $dbh->do(q|UPDATE items SET notforloan=0 WHERE biblionumber=?|, {}, $biblionumber );
221         $dbh->do(q|UPDATE biblioitems SET itemtype=? WHERE biblionumber=?|, {}, $itemtype->{itemtype}, $biblionumber);
222         $dbh->do(q|UPDATE items SET itype=? WHERE biblionumber=?|, {}, $itemtype->{itemtype}, $biblionumber);
223     }
224
225     time_diff("add items");
226
227     my $nb_of_checkouts = 0;
228     for my $biblionumber ( @biblionumbers ) {
229         $driver->get($base_url."/circ/circulation.pl?borrowernumber=".$borrowernumber);
230         $driver->find_element('//input[@id="barcode"]')->send_keys('t_value_bib'.$biblionumber);
231         $driver->find_element('//fieldset[@id="circ_circulation_issue"]/button[@type="submit"]')->click;
232         $nb_of_checkouts++;
233         like( $driver->get_title(), qr(Checking out to $sample_data->{patron}{surname}) );
234         is( $driver->find_element('//a[@href="#checkouts"]')->get_attribute('text'), $nb_of_checkouts.' Checkout(s)', );
235     }
236
237     time_diff("checkout");
238
239     for my $biblionumber ( @biblionumbers ) {
240         $driver->get($base_url."/circ/returns.pl");
241         $driver->find_element('//input[@id="barcode"]')->send_keys('t_value_bib'.$biblionumber);
242         $driver->find_element('//*[@id="circ_returns_checkin"]/div[2]/div[1]/div[2]/button')->click;
243         like( $driver->get_title(), qr(Check in test biblio \d+) );
244     }
245
246     time_diff("checkin");
247
248     #Place holds
249     $driver->get($base_url."/reserve/request.pl?borrowernumber=$borrowernumber&biblionumber=".$biblionumbers[0]);
250     $driver->find_element('//form[@id="hold-request-form"]//button[@type="submit"]')->click; # Biblio level
251     $driver->pause(1000); # This seems wrong, since bug 19618 the hold is created async with an AJAX call. Not sure what is happening here but the next statements are exectuted before the hold is created and the count is wrong (still 0)
252     my $patron = Koha::Patrons->find($borrowernumber);
253     is( $patron->holds->count, 1, );
254
255     $driver->get($base_url."/reserve/request.pl?borrowernumber=$borrowernumber&biblionumber=".$biblionumbers[1]);
256     $driver->find_element('//form[@id="hold-request-form"]//input[@type="radio"]')->click; # Item level, there is only 1 item per bib so we are safe
257     $driver->find_element('//form[@id="hold-request-form"]//button[@type="submit"]')->click;
258     $driver->pause(1000);
259     is( $patron->holds->count, 2, );
260
261     time_diff("holds");
262
263     close $fh;
264     $driver->quit();
265 };
266
267 END {
268     cleanup() if $cleanup_needed;
269 };
270
271 sub cleanup {
272     my $dbh = C4::Context->dbh;
273     $dbh->do(q|DELETE FROM issues where borrowernumber=?|, {}, $borrowernumber);
274     $dbh->do(q|DELETE FROM old_issues where borrowernumber=?|, {}, $borrowernumber);
275     for my $i ( 1 .. $number_of_biblios_to_insert ) {
276         $dbh->do(qq|DELETE items, biblio FROM biblio INNER JOIN items ON biblio.biblionumber = items.biblionumber WHERE biblio.title = "test biblio$i"|);
277     };
278     $dbh->do(q|DELETE FROM borrowers WHERE userid = ?|, {}, $sample_data->{patron}{userid});
279     $dbh->do(q|DELETE FROM categories WHERE categorycode = ?|, {}, $sample_data->{category}{categorycode});
280     for my $i ( 1 .. $number_of_biblios_to_insert ) {
281         $dbh->do(qq|DELETE FROM biblio WHERE title = "test biblio $i"|);
282     };
283     $dbh->do(q|DELETE FROM itemtypes WHERE itemtype=?|, undef, $sample_data->{itemtype}{itemtype});
284     $dbh->do(q|DELETE FROM circulation_rules WHERE categorycode=? AND itemtype=? AND branchcode=?|, undef, $sample_data->{issuingrule}{categorycode}, $sample_data->{issuingrule}{itemtype}, $sample_data->{issuingrule}{branchcode});
285 }
286
287 sub time_diff {
288     my $lib = shift;
289     my $now = gettimeofday;
290     warn "CP $lib = " . sprintf("%.2f", $now - $prev_time ) . "\n";
291     $prev_time = $now;
292 }