View | Details | Raw Unified | Return to bug 14536
Collapse All | Expand All

(-)a/misc/devel/interactiveWebDriverShell.pl (+202 lines)
Line 0 Link Here
1
#!/usr/bin/perl -d
2
3
# Copyright 2015 KohaSuomi
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, see <http://www.gnu.org/licenses>.
18
19
=head1 NAME
20
21
interactiveWebDriverShell.pl
22
23
=head1 SYNOPSIS
24
25
    misc/devel/interactiveWebDriverShell.pl -p mainpage.pl
26
27
Prepares a perl debugger session with the requested PageObject loaded.
28
Then you can easily guide the UserAgent through the web session.
29
30
=cut
31
32
use Modern::Perl;
33
34
use Getopt::Long qw(:config no_ignore_case);
35
use Data::Dumper;
36
37
my ($help, $page, $list, @params, @login);
38
39
GetOptions(
40
    "h|help"        => \$help,
41
    "p|page=s"      => \$page,
42
    "P|params=s{,}" => \@params,
43
    "L|login=s{,}"  => \@login,
44
    "l|list"        => \$list,
45
);
46
47
my $help_msg = <<HELP;
48
49
interactiveWebDriverShell.pl
50
51
    Prepares a perl debugger session with the requested PageObject loaded.
52
    Then you can easily guide the UserAgent through the web session.
53
54
    You should install Term::ReadLine::Gnu for a more pleasant debugging experience.
55
56
    -h --help   This help!
57
58
    -p --page   Which PageObject matching the given page you want to preload?
59
60
    -P --params List of parameters the PageObject must have.
61
62
    -L --login  List of userid and password to automatically login to Koha. Eg:
63
                ./interactiveWebDriverShell.pl -L admin 1234 -p members/moremember.pl -P 12
64
65
    -l --list   Lists available PageObjects and their matching --page -parameter
66
                values.
67
68
EXAMPLE INVOCATIONS:
69
70
./interactiveWebDriverShell.pl -p mainpage.pl -L admin 1234
71
./interactiveWebDriverShell.pl -p members/moremember.pl -P 1 -L admin 1234
72
73
USAGE:
74
75
Start the session from your shell
76
    ..\$ misc/devel/interactiveWebDriverShell.pl -p mainpage.pl
77
or
78
Start the session from your shell with parameters
79
    ..\$ misc/devel/interactiveWebDriverShell.pl -p members/moremember.pl -P 12
80
81
Continue to the breakpoint set in this script
82
    DB<1> c
83
84
The PageObject is bound to variable \$po,
85
and the Selenium::Remote::Driver-implementation to \$d.
86
Then all you need to do is start navigating the web!
87
    DB<2> \$po->isPasswordLoginAvailable()->doPasswordLogin('admin','1234');
88
89
    DB<3> \$ele = \$d->find_element('input[value="Save"]');
90
91
Note! Do not use "my \$ele = 123;" in the debugger session, because that doesn't
92
work as excepted, simply use "\$ele = 123;".
93
94
HELP
95
96
if ($help) {
97
    print $help_msg;
98
    exit;
99
}
100
unless ($page || $list) {
101
    print $help_msg;
102
    exit;
103
}
104
105
my $supportedPageObjects = {
106
################################################################################
107
  ########## STAFF CONFIGURATIONS ##########
108
################################################################################
109
    'mainpage.pl' =>
110
    {   package     => "t::lib::Page::Mainpage",
111
        urlEndpoint => "mainpage.pl",
112
        status      => "OK",
113
        params      => "none",
114
    },
115
    "members/moremember.pl" =>
116
    {   package     => "t::lib::Page::Members::Moremember",
117
        urlEndpoint => "members/moremember.pl",
118
        status      => "not implemented",
119
        params      => ["borrowernumber"],
120
    },
121
    "members/statistics.pl" =>
122
    {   package     => "t::lib::Page::Members::Statistics",
123
        urlEndpoint => "members/statistics.pl",
124
        status      => "OK",
125
        params      => ["borrowernumber"],
126
    },
127
    "members/member-flags.pl" =>
128
    {   package     => "t::lib::Page::Members::MemberFlags",
129
        urlEndpoint => "members/member-flags.pl",
130
        status      => "not implemented",
131
        params      => ["borrowernumber"],
132
    },
133
    "catalogue/detail.pl" =>
134
    {   package     => "t::lib::Page::Catalogue::Detail",
135
        urlEndpoint => "catalogue/detail.pl",
136
        status      => "OK",
137
        params      => ["biblionumber"],
138
    },
139
################################################################################
140
  ########## OPAC CONFIGURATIONS ##########
141
################################################################################
142
    "opac/opac-main.pl" =>
143
    {   package     => "t::lib::Page::Opac::OpacMain",
144
        urlEndpoint => "opac/opac-main.pl",
145
        status      => "OK",
146
    },
147
};
148
################################################################################
149
  ########## END OF PAGE CONFIGURATIONS ##########
150
################################################################################
151
152
listSupportedPageObjects ($supportedPageObjects) if $list;
153
my ($po, $d) = deployPageObject($supportedPageObjects, $page, \@params, \@login) if $page;
154
155
156
157
print "--Debugging--\n";
158
$DB::single = 1; #Breakpoint here
159
$DB::single = 1;
160
161
162
163
sub listSupportedPageObjects {
164
    my ($supportedPageObjects) = @_;
165
    print Data::Dumper::Dumper($supportedPageObjects);
166
    exit;
167
}
168
sub deployPageObject {
169
    my ($supportedPageObjects, $page, $params, $login) = @_;
170
171
    ##Find correct PageObject deployment rules
172
    my $pageObjectMapping = $supportedPageObjects->{$page};
173
    die "No PageObject mapped to --page '$page'. See --list to list available PageObjects.\n" unless $pageObjectMapping;
174
175
    ##Dynamically load package
176
    my $package = $pageObjectMapping->{package};
177
    eval "require $package";
178
179
    ##Fill required parameters
180
    my $poParams = {};
181
    if (ref($pageObjectMapping->{params}) eq 'ARRAY') {
182
        foreach my $paramName (@{$pageObjectMapping->{params}}) {
183
            $poParams->{$paramName} = shift(@$params);
184
            die "Insufficient parameters given, parameter '$paramName' unsatisfied.\n" unless $poParams->{$paramName};
185
        }
186
    }
187
188
    ##Check if the status is OK
189
    die "PageObject status for '$page' is not 'OK'. Current status '".$pageObjectMapping->{status}."'.\nPlease implement the missing PageObject.\n" unless $pageObjectMapping->{status} eq 'OK';
190
191
    ##Create PageObject
192
    my $po = $package->new($poParams);
193
194
    ##Password login if desired
195
    eval {
196
       $po->isPasswordLoginAvailable->doPasswordLogin($login->[0], $login->[1]) if scalar(@$login);
197
    }; if ($@) {
198
        print "Password login unavailable.\n";
199
    }
200
201
    return ($po, $po->getDriver());
202
}
(-)a/t/db_dependent/Koha/Auth.t (+72 lines)
Line 0 Link Here
1
#!/usr/bin/env perl
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use Test::More;
23
use Try::Tiny; #Even Selenium::Remote::Driver uses Try::Tiny :)
24
25
use t::lib::Page::Mainpage;
26
27
use t::lib::TestObjects::PatronFactory;
28
29
##Setting up the test context
30
my $testContext = {};
31
32
my $password = '1234';
33
my $borrowerFactory = t::lib::TestObjects::PatronFactory->new();
34
my $borrowers = $borrowerFactory->createTestGroup([
35
            {firstname  => 'Olli-Antti',
36
             surname    => 'Kivi',
37
             cardnumber => '1A01',
38
             branchcode => 'CPL',
39
             flags      => '1', #superlibrarian, not exactly a very good way of doing permission testing?
40
             userid     => 'mini_admin',
41
             password   => $password,
42
            },
43
        ], undef, $testContext);
44
45
##Test context set, starting testing:
46
eval { #run in a eval-block so we don't die without tearing down the test context
47
48
    testPasswordLogin();
49
50
};
51
if ($@) { #Catch all leaking errors and gracefully terminate.
52
    warn $@;
53
    tearDown();
54
    exit 1;
55
}
56
57
##All tests done, tear down test context
58
tearDown();
59
done_testing;
60
61
sub tearDown {
62
    t::lib::TestObjects::ObjectFactory->tearDownTestContext($testContext);
63
}
64
65
######################################################
66
    ###  STARTING TEST IMPLEMENTATIONS         ###
67
######################################################
68
69
sub testPasswordLogin {
70
    my $mainpage = t::lib::Page::Mainpage->new();
71
    $mainpage->isPasswordLoginAvailable()->doPasswordLogin($borrowers->{'1A01'}->userid(), $password)->quit();
72
}
(-)a/t/lib/Page.pm (+344 lines)
Line 0 Link Here
1
package t::lib::Page;
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Test::More;
22
23
use C4::Context;
24
25
use t::lib::WebDriverFactory;
26
27
use Koha::Exception::BadParameter;
28
use Koha::Exception::SystemCall;
29
30
=head NAME t::lib::Page
31
32
=head SYNOPSIS
33
34
PageObject-pattern parent class. Extend this to implement specific pages shown to our users.
35
36
PageObjects are used to make robust and reusable integration test components to test
37
various front-end features. PageObjects load a Selenium::Remote::Driver implementation,
38
phantomjs by default and use this to do scripted user actions in the browser,
39
eg. clicking HTML-elements, accepting popup dialogs, entering text to input fields.
40
41
PageObjects encapsulate those very low-level operations into clear and easily usable
42
actions or services, like doPasswordLogin().
43
PageObjects also seamlessly deal with navigation from one page to another, eg.
44
    my $mainpage = t::lib::Page::Mainpage->new();
45
    $mainpage->doPasswordLogin('admin', '1234')->gotoPatrons()->
46
               searchPatrons({keywordSearch => "Jane Doe"});
47
48
=head Class variables
49
50
Selenium::Remote::Driver driver, contains the driver implementation used to run these tests
51
t::Page::Common::Header  header, the header page component (not implemented)
52
t::Page::Common::Footer  footer, the footer page component (not implemented)
53
Scalar                   userInteractionDelay, How many milliseconds to wait for javascript
54
                                               to stop processing by default after user actions?
55
56
=head DEBUGGING
57
58
Set Environment value
59
    $ENV{KOHA_PAGEOBJECT_DEBUG} = 1;
60
Before creating the first PageObject to enable debugging.
61
Debugging output is written to /tmp/PageObjectDebug/ by default, but you can change it
62
using the same environment variable
63
    $ENV{KOHA_PAGEOBJECT_DEBUG} = "/tmp/generalDebugging/";
64
65
=cut
66
67
sub new {
68
    my ($class, $params) = @_;
69
    $params = _mergeDefaultConfig($params);
70
71
    my $self = {};
72
    bless($self, $class);
73
    unless ($params->{driver}) {
74
        my ($driver) = t::lib::WebDriverFactory::getUserAgentDrivers({phantomjs => $params});
75
        $self->{driver} = $driver;
76
    }
77
    $self->{type}     = $params->{type}; #This parameter is mandatory. _mergeDefaultConfig() dies without it.
78
    $self->{resource} = $params->{resource} || '/';
79
    $self->{resource} .= "?".join('&', @{$params->{getParams}}) if $params->{getParams};
80
    $self->{header}   = $params->{header}   || undef;
81
    $self->{footer}   = $params->{footer}   || undef;
82
83
    $self->{userInteractionDelay} = $params->{userInteractionDelay} || 500;
84
85
    $self->{driver}->set_window_size(1280, 960);
86
    $self->{driver}->get( $self->{resource} );
87
88
    $self->debugSetEnvironment(); #If debugging is enabled
89
90
    return $self;
91
}
92
93
=head rebrandFromPageObject
94
When we are getting redirected from one page to another we rebrand the existing PageObject
95
as another PageObject to have the new page's services available.
96
97
@RETURNS The desired new PageObject Page
98
=cut
99
100
sub rebrandFromPageObject {
101
    my ($class, $self) = @_;
102
    bless($self, $class);
103
    my $d = $self->getDriver();
104
    $d->pause(250); #Wait for javascript to load.
105
    $self->debugTakeSessionSnapshot();
106
    ok(1, "Navigated to $class");
107
    return $self;
108
}
109
110
=head _mergeDefaultConfig
111
112
@THROWS Koha::Exception::BadParameter
113
=cut
114
115
sub _mergeDefaultConfig {
116
    my ($params) = @_;
117
    unless (ref($params) eq 'HASH' && $params->{type}) {
118
        Koha::Exception::BadParameter->throw(error => "t::lib::Page:> When instantiating Page-objects, you must define the 'type'-parameter.");
119
    }
120
121
    my $testServerConfigs = C4::Context->config('testservers');
122
    my $conf = $testServerConfigs->{ $params->{type} };
123
    Koha::Exception::BadParameter->throw(error => "t::lib::Page:> Unknown 'type'-parameter '".$params->{type}."'. Values 'opac', 'staff' and 'rest' are supported.")
124
                unless $conf;
125
    #Merge given $params-config on top of the $KOHA_CONF's testservers-directives
126
    @$conf{keys %$params} = values %$params;
127
    return $conf;
128
}
129
130
=head quit
131
Wrapper for Selenium::Remote::Driver->quit(),
132
Delete the session & close open browsers.
133
134
When ending this browser session, it is polite to quit, or there is a risk of leaving
135
floating test browsers floating around.
136
=cut
137
138
sub quit {
139
    my ($self) = @_;
140
    $self->getDriver()->quit();
141
}
142
143
=head pause
144
Wrapper for Selenium::Remote::Driver->pause(),
145
=cut
146
147
sub pause {
148
    my ($self, $pauseMillis) = @_;
149
    $self->getDriver()->pause($pauseMillis);
150
    return $self;
151
}
152
153
=head
154
Wrapper for Selenium::Remote::Driver->refresh()
155
=cut
156
157
sub refresh {
158
    my ($self) = @_;
159
    $self->getDriver()->refresh();
160
    $self->debugTakeSessionSnapshot();
161
    return $self;
162
}
163
164
=head poll
165
Polls anonymous subroutine $func at given rate $pauseMillis for given times $polls or
166
until $func succeeds without exceptions.
167
168
In case of an exception, optional anonymous subroutine $success is called to confirm
169
whether or not the action was successful. If this subroutine is not defined or it returns
170
false, polling continues.
171
172
Default pause for polling is 50ms and the polling runs by default for 20 times.
173
174
@PARAM1 $func                  Anonymous subroutine to be polled
175
@PARAM2 $success      OPTIONAL Success function to check if action was successful
176
@PARAM3 $polls        OPTIONAL Defines the times polling will be ran
177
@PARAM4 $pauseMillis  OPTIONAL Defines the wait between two polls
178
179
@RETURNS 1 if polling was success, otherwise die
180
=cut
181
182
sub poll {
183
    my ($self, $func, $success, $polls, $pauseMillis) = @_;
184
185
    # initialize default values if not given
186
    $polls = 20 unless defined $polls;
187
    $pauseMillis = 50 unless defined $pauseMillis;
188
189
    for (my $i = 0; $i < $polls; $i++){
190
        eval {
191
            &$func();
192
        };
193
        if ($@) {
194
            return 1 if defined $success and &$success();
195
            $self->getDriver()->pause($pauseMillis);
196
            next;
197
        }
198
        return 1 unless $@; # if no errors, return true
199
    }
200
    die $@;
201
}
202
203
=head mockConfirmPopup
204
205
Workaround to a missing feature in PhantomJS v1.9
206
Confirm popup's cannot be negotiated with. This preparatory method makes confirm dialogs
207
always return 'true' or 'false' without showing the actual dialog.
208
209
@PARAM1 Boolean, the confirm popup dialog's return value.
210
211
=cut
212
213
sub mockConfirmPopup {
214
    my ($self, $retVal) = @_;
215
    my $d = $self->getDriver();
216
217
    my $script = q{
218
        var retVal = (arguments[0] == 1) ? true : false;
219
        var callback = arguments[arguments.length-1];
220
        window.confirm = function(){return retVal;};
221
        callback();
222
    };
223
    $d->execute_async_script($script, ($retVal ? 1 : 0));
224
}
225
226
=head mockPromptPopup
227
228
Workaround to a missing feature in PhantomJS v1.9
229
Prompt popup's cannot be negotiated with. This preparatory method makes prompt dialogs
230
always return 'true' or 'false' without showing the actual dialog.
231
232
@PARAM1 Boolean, the prompt popup dialog's return value.
233
234
=cut
235
236
sub mockPromptPopup {
237
    my ($self, $retVal) = @_;
238
    my $d = $self->getDriver();
239
240
    my $script = q{
241
        var callback = arguments[arguments.length-1];
242
        window.prompt = function(){return arguments[0];};
243
        callback();
244
    };
245
    $d->execute_async_script($script, ($retVal ? 1 : 0));
246
}
247
248
=head mockAlertPopup
249
250
Workaround to a missing feature in PhantomJS v1.9
251
Alert popup's cannot be negotiated with and they freeze PageObject testing.
252
This preparatory method makes alert dialogs always return NULL without showing
253
the actual dialog.
254
255
=cut
256
257
sub mockAlertPopup {
258
    my ($self, $retVal) = @_;
259
    my $d = $self->getDriver();
260
261
    my $script = q{
262
        var callback = arguments[arguments.length-1];
263
        window.alert = function(){return;};
264
        callback();
265
    };
266
    $d->execute_async_script($script);
267
}
268
269
################################################
270
  ##  INTRODUCING OBJECT ACCESSORS  ##
271
################################################
272
sub setDriver {
273
    my ($self, $driver) = @_;
274
    $self->{driver} = $driver;
275
}
276
sub getDriver {
277
    my ($self) = @_;
278
    return $self->{driver};
279
}
280
281
################################################
282
  ##  INTRODUCING TESTING HELPERS  ##
283
################################################
284
sub debugSetEnvironment {
285
    my ($self) = @_;
286
    if ($ENV{KOHA_PAGEOBJECT_DEBUG}) {
287
        $self->{debugSessionId} = sprintf("%03i",rand(999));
288
        $self->{debugSessionTmpDirectory} = "/tmp/PageObjectDebug/";
289
        $self->{debugSessionTmpDirectory} = $ENV{KOHA_PAGEOBJECT_DEBUG} if (not(ref($ENV{KOHA_PAGEOBJECT_DEBUG})) && length($ENV{KOHA_PAGEOBJECT_DEBUG}) > 1);
290
        my $error = system(("mkdir", "-p", $self->{debugSessionTmpDirectory}));
291
        Koha::Exception::SystemCall->throw(error => "Trying to create a temporary directory for PageObject debugging session '".$self->{debugSessionId}."' failed:\n  $?")
292
                if $error;
293
        $self->{debugInternalCounter} = 1;
294
295
        print "\n\n--Starting PageObject debugging session '".$self->{debugSessionId}."'\n\n";
296
    }
297
}
298
299
sub debugTakeSessionSnapshot {
300
    my ($self) = @_;
301
    if ($ENV{KOHA_PAGEOBJECT_DEBUG}) {
302
        my ($actionIdentifier, $actionFile) = $self->_debugGetSessionIdentifier(2);
303
304
        $self->_debugWriteHTML($actionIdentifier, $actionFile);
305
        $self->_debugWriteScreenshot($actionIdentifier, $actionFile);
306
        $self->{debugInternalCounter}++;
307
    }
308
}
309
310
sub _debugGetSessionIdentifier {
311
    my ($self, $callerDepth) = @_;
312
    $callerDepth = $callerDepth || 2;
313
    ##Create a unique and descriptive identifier for this program state.
314
    my ($package, $filename, $line, $subroutine) = caller($callerDepth); #Get where we are called from
315
    $subroutine = $2 if ($subroutine =~ /(::|->)([^:->]+)$/); #Get the last part of the package, the subroutine name.
316
    my $actionIdentifier = "[session '".$self->{debugSessionId}."', counter '".sprintf("%03i",$self->{debugInternalCounter})."', caller '$subroutine']";
317
    my $actionFile = $self->{debugSessionId}.'_'.sprintf("%03i",$self->{debugInternalCounter}).'_'.$subroutine;
318
    return ($actionIdentifier, $actionFile);
319
}
320
321
sub _debugWriteHTML {
322
    require Data::Dumper;
323
    my ($self, $actionIdentifier, $actionFile) = @_;
324
    my $d = $self->getDriver();
325
326
    ##Write the current Response data
327
    open(my $fh, ">:encoding(UTF-8)", $self->{debugSessionTmpDirectory}.$actionFile.'.html')
328
                or die "Trying to open a filehandle for PageObject debugging output $actionIdentifier:\n  $@";
329
    print $fh $d->get_title()."\n";
330
    print $fh "ALL COOKIES DUMP:\n".Data::Dumper::Dumper($d->get_all_cookies());
331
    print $fh $d->get_page_source()."\n";
332
    close $fh;
333
}
334
335
sub _debugWriteScreenshot {
336
    my ($self, $actionIdentifier, $actionFile) = @_;
337
    my $d = $self->getDriver();
338
339
    ##Write a screenshot of the view to file.
340
    my $ok = $d->capture_screenshot($self->{debugSessionTmpDirectory}.$actionFile.'.png');
341
    Koha::Exception::SystemCall->throw(error => "Cannot capture a screenshot for PageObject $actionIdentifier")
342
                unless $ok;
343
}
344
1; #Make the compiler happy!
(-)a/t/lib/Page/Catalogue/Detail.pm (+150 lines)
Line 0 Link Here
1
package t::lib::Page::Catalogue::Detail;
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Scalar::Util qw(blessed);
22
use Test::More;
23
24
use t::lib::Page::Catalogue::Search;
25
26
use base qw(t::lib::Page::Intra t::lib::Page::Catalogue::Toolbar);
27
28
use Koha::Exception::BadParameter;
29
30
=head NAME t::lib::Page::Catalogue::Detail
31
32
=head SYNOPSIS
33
34
detail.pl PageObject providing page functionality as a service!
35
36
=cut
37
38
=head new
39
40
    my $detail = t::lib::Page::Catalogue::Detail->new({biblionumber => "1"})->doPasswordLogin('admin', '2134');
41
42
Instantiates a WebDriver and loads the catalogue/detail.pl to show the given Biblio
43
@PARAM1 HASHRef of optional and MANDATORY parameters
44
MANDATORY extra parameters:
45
    biblionumber => loads the page to display the Biblio matching the given parameter
46
47
@RETURNS t::lib::Page::Catalogue::Detail, ready for user actions!
48
=cut
49
50
sub new {
51
    my ($class, $params) = @_;
52
    unless (ref($params) eq 'HASH' || (blessed($params) && $params->isa('t::lib::Page') )) {
53
        $params = {};
54
    }
55
    $params->{resource} = '/cgi-bin/koha/catalogue/detail.pl';
56
    $params->{type}     = 'staff';
57
58
    $params->{getParams} = [];
59
    #Handle MANDATORY parameters
60
    if ($params->{biblionumber}) {
61
        push @{$params->{getParams}}, "biblionumber=".$params->{biblionumber};
62
    }
63
    else {
64
        Koha::Exception::BadParameter->throw(error => __PACKAGE__."->new():> Parameter 'borrowernumber' is missing.");
65
    }
66
67
    my $self = $class->SUPER::new($params);
68
69
    return $self;
70
}
71
72
################################################################################
73
=head UI Mapping helper subroutines
74
See. Selenium documentation best practices for UI element mapping to common language descriptions.
75
=cut
76
################################################################################
77
78
=head _getBiblioMarkers
79
80
@RETURNS HASHRef of Biblio data elements of the displayed Biblio details.
81
            'title' is guaranteed, others are optional
82
=cut
83
84
sub _getBiblioMarkers {
85
    my ($self) = @_;
86
    my $d = $self->getDriver();
87
88
    my $e = {};
89
    $e->{title} = $d->find_element("#catalogue_detail_biblio .title", 'css')->get_text(); #title is mandatory and should always exist to simplify testing.
90
    eval {
91
        $e->{author} = $d->find_element("#catalogue_detail_biblio .author a", 'css')->get_text();
92
    };
93
    eval {
94
        $e->{isbn} = $d->find_element("#catalogue_detail_biblio span[property='isbn']", 'css')->get_text();
95
    };
96
    return $e;
97
}
98
99
100
101
################################################################################
102
=head PageObject Services
103
104
=cut
105
################################################################################
106
107
=head isBiblioMatch
108
109
    $detail->isBiblioMatch($record);
110
111
Checks that the loaded Biblio matches the give MARC::Record.
112
=cut
113
114
sub isBiblioMatch {
115
    my ($self, $record) = @_;
116
    $self->debugTakeSessionSnapshot();
117
118
    my $e = $self->_getBiblioMarkers();
119
    my $testFail;
120
    if (not($record->title() eq $e->{title})) {
121
        $testFail = 1;
122
    }
123
    if ($record->author() && not($record->author() eq $e->{author})) {
124
        $testFail = 1;
125
    }
126
127
    ok(not($testFail), "Biblio '".$record->title()."' matches loaded Biblio");
128
    return $self;
129
}
130
131
=head deleteBiblio
132
Deletes the displayed Biblio
133
134
@RETURNS t::lib::PageObject::Catalogue::Search as the execution moves to that PageObject.
135
=cut
136
137
sub deleteBiblio {
138
    my ($self) = @_;
139
    my $d = $self->getDriver();
140
    $self->debugTakeSessionSnapshot();
141
142
    my $e = $self->_getEditDropdownElements();
143
    $self->mockConfirmPopup('true');
144
    $e->{deleteRecord}->click();
145
146
    return t::lib::Page::Catalogue::Search->rebrandFromPageObject($self);
147
}
148
149
150
1; #Make the compiler happy!
(-)a/t/lib/Page/Catalogue/Search.pm (+107 lines)
Line 0 Link Here
1
package t::lib::Page::Catalogue::Search;
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Scalar::Util qw(blessed);
22
use Time::HiRes;
23
use Test::More;
24
25
use base qw(t::lib::Page::Intra t::lib::Page::Catalogue::Toolbar);
26
27
use Koha::Exception::UnknownObject;
28
29
=head NAME t::lib::Page::Catalogue::Search
30
31
=head SYNOPSIS
32
33
search.pl PageObject providing page functionality as a service!
34
35
=cut
36
37
=head new
38
39
    my $search = t::lib::Page::Catalogue::Search->new()->doPasswordLogin('admin', '2134');
40
41
Instantiates a WebDriver and loads the catalogue/search.pl to show the given Biblio
42
@PARAM1 HASHRef of optional and MANDATORY parameters
43
44
@RETURNS t::lib::Page::Catalogue::Search, ready for user actions!
45
=cut
46
47
sub new {
48
    my ($class, $params) = @_;
49
    unless (ref($params) eq 'HASH' || (blessed($params) && $params->isa('t::lib::Page') )) {
50
        $params = {};
51
    }
52
    $params->{resource} = '/cgi-bin/koha/catalogue/search.pl';
53
    $params->{type}     = 'staff';
54
55
    $params->{getParams} = [];
56
57
    my $self = $class->SUPER::new($params);
58
59
    return $self;
60
}
61
62
=head rebrandFromPageObject
63
@EXTENDS t::lib::Page->rebrandFromPageObject()
64
65
Checks that the rebranding succeeds by making sure that the page we are rebranding to
66
is the page we have.
67
=cut
68
69
sub rebrandFromPageObject {
70
    my ($class, $self) = @_;
71
    my $d = $self->getDriver();
72
73
    my $waitCycles = 0;
74
    while ($waitCycles <= 10 &&
75
           $d->get_current_url() !~ m!catalogue/search.pl! ) {
76
        Time::HiRes::usleep(250000);
77
        $waitCycles++;
78
    }
79
80
    if ($waitCycles > 10) {
81
        my ($package, $filename, $line, $subroutine) = caller(1);
82
        Koha::Exception::UnknownObject->throw(error => __PACKAGE__."->rebrandFromPageObject():> Timeout looking for proper Page markers. This is not a 'catalogue/search.pl'-page!\n    Called from $package->$subroutine");
83
    }
84
    return $class->SUPER::rebrandFromPageObject($self);
85
}
86
87
################################################################################
88
=head UI Mapping helper subroutines
89
See. Selenium documentation best practices for UI element mapping to common language descriptions.
90
=cut
91
################################################################################
92
93
94
95
96
97
################################################################################
98
=head PageObject Services
99
100
=cut
101
################################################################################
102
103
104
105
106
107
1; #Make the compiler happy!
(-)a/t/lib/Page/Catalogue/Toolbar.pm (+136 lines)
Line 0 Link Here
1
package t::lib::Page::Catalogue::Toolbar;
2
3
# Copyright 2015 KohaSuomi!
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Test::More;
22
23
use Koha::Exception::BadParameter;
24
25
=head NAME t::lib::Page::Catalogue::Toolbar
26
27
=head SYNOPSIS
28
29
PageObject Accessory representing a shared Template between PageObjects.
30
This encapsulates specific page-related functionality.
31
32
In this case this encapsulates the members-module toolbar's services and provides
33
a reusable class from all member-module PageObjects.
34
35
=cut
36
37
################################################################################
38
=head UI Mapping helper subroutines
39
See. Selenium documentation best practices for UI element mapping to common language descriptions.
40
=cut
41
################################################################################
42
43
=head _getToolbarActionElements
44
@RETURNS HASHRef of Selenium::Driver::Webelements matching all the clickable elements
45
                 in the actions toolbar over the Biblio information.
46
=cut
47
48
sub _getToolbarActionElements {
49
    my ($self) = @_;
50
    my $d = $self->getDriver();
51
52
    my $e = {};
53
    eval {
54
        $e->{new}       = $d->find_element("#newDropdownContainer button", 'css');
55
    };
56
    eval {
57
        $e->{edit}      = $d->find_element("#editDropdownContainer button", 'css');
58
    };
59
    eval {
60
        $e->{save}      = $d->find_element("#saveDropdownContainer button", 'css');
61
    };
62
    eval {
63
        $e->{addTo}     = $d->find_element("#addtoDropdownContainer button", 'css');
64
    };
65
    eval {
66
        $e->{print}     = $d->find_element("#printbiblio", 'css');
67
    };
68
    eval {
69
        $e->{placeHold} = $d->find_element("#placeholdDropdownContainer button", 'css');
70
    };
71
    return $e;
72
}
73
74
=head _getEditDropdownElements
75
Clicks the dropdown open if it isnt yet.
76
@RETURNS HASHRef of all the dropdown elements under the Edit button in the toolbar
77
                 over Biblio information.
78
=cut
79
80
sub _getEditDropdownElements {
81
    my ($self) = @_;
82
    my $d = $self->getDriver();
83
84
    my $toolbarElements = $self->_getToolbarActionElements();
85
    my $editButton = $toolbarElements->{edit};
86
    my $dropdownElement;
87
    eval {
88
        $dropdownElement = $d->find_child_element($editButton, "#editDropdownContainer ul a:nth-of-type(1)", 'css');
89
    };
90
    unless ($dropdownElement && $dropdownElement->is_visible()) {
91
        $editButton->click();
92
        $self->debugTakeSessionSnapshot();
93
    }
94
95
    my $e = {};
96
    eval {
97
        $e->{editRecord}         = $d->find_element("a[id|='editbiblio']", 'css');
98
    };
99
    eval {
100
        $e->{editItems}          = $d->find_element("a[id|='edititems']", 'css');
101
    };
102
    eval {
103
        $e->{editItemsInBatch}   = $d->find_element("a[id|='batchedit']", 'css');
104
    };
105
    eval {
106
        $e->{deleteItemsInBatch} = $d->find_element("a[id|='batchdelete']", 'css');
107
    };
108
    eval {
109
        $e->{attachItem}         = $d->find_element("a[href*='cataloguing/moveitem.pl']", 'css');
110
    };
111
    eval {
112
        $e->{editAsNew}          = $d->find_element("a[id|='duplicatebiblio']", 'css');
113
    };
114
    eval {
115
        $e->{replaceRecord}      = $d->find_element("a[id|='z3950copy']", 'css');
116
    };
117
    eval {
118
        $e->{deleteRecord}       = $d->find_element("a[id|='deletebiblio']", 'css');
119
    };
120
    eval {
121
        $e->{deleteAllItems}     = $d->find_element("a[id|='deleteallitems']", 'css');
122
    };
123
    return $e;
124
}
125
126
127
################################################################################
128
=head PageObject Services
129
130
=cut
131
################################################################################
132
133
134
135
136
1; #Make the compiler happy!
(-)a/t/lib/Page/Circulation/Circulation.pm (+76 lines)
Line 0 Link Here
1
package t::lib::Page::Circulation::Circulation;
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Scalar::Util qw(blessed);
22
use Test::More;
23
24
use base qw(t::lib::Page::Intra t::lib::Page::Members::Toolbar t::lib::Page::Members::LeftNavigation);
25
26
use Koha::Exception::BadParameter;
27
28
=head NAME t::lib::Page::Circulation::Circulation
29
30
=head SYNOPSIS
31
32
circulation.pl PageObject providing page functionality as a service!
33
34
=cut
35
36
=head new
37
38
    my $circulation = t::lib::Page::Circulation::Circulation->new({borrowernumber => "1"});
39
40
Instantiates a WebDriver and loads the circ/circulation.pl.
41
@PARAM1 HASHRef of optional and MANDATORY parameters
42
MANDATORY extra parameters:
43
    borrowernumber => loads the page to display Borrower matching the given borrowernumber
44
45
@RETURNS t::lib::Page::Circulation::Circulation, ready for user actions!
46
=cut
47
48
sub new {
49
    my ($class, $params) = @_;
50
    unless (ref($params) eq 'HASH' || (blessed($params) && $params->isa('t::lib::Page') )) {
51
        $params = {};
52
    }
53
    $params->{resource} = '/cgi-bin/koha/circ/circulation.pl';
54
    $params->{type}     = 'staff';
55
56
    $params->{getParams} = [];
57
    #Handle MANDATORY parameters
58
    if ($params->{borrowernumber}) {
59
        push @{$params->{getParams}}, "borrowernumber=".$params->{borrowernumber};
60
    }
61
    else {
62
        Koha::Exception::BadParameter->throw(error => __PACKAGE__."->new():> Parameter 'borrowernumber' is missing.");
63
    }
64
65
    my $self = $class->SUPER::new($params);
66
67
    return $self;
68
}
69
70
################################################################################
71
=head UI Mapping helper subroutines
72
See. Selenium documentation best practices for UI element mapping to common language descriptions.
73
=cut
74
################################################################################
75
76
1;
(-)a/t/lib/Page/Intra.pm (+228 lines)
Line 0 Link Here
1
package t::lib::Page::Intra;
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Test::More;
22
23
use C4::Context;
24
25
use t::lib::WebDriverFactory;
26
27
use Koha::Exception::BadParameter;
28
use Koha::Exception::SystemCall;
29
30
use base qw(t::lib::Page);
31
32
=head NAME t::lib::Page::Intra
33
34
=head SYNOPSIS
35
36
PageObject-pattern parent class for Intranet-pages (staff client). Extend this to implement specific pages shown to our users.
37
38
=cut
39
40
################################################################################
41
=head UI Mapping helper subroutines
42
See. Selenium documentation best practices for UI element mapping to common language descriptions.
43
=cut
44
################################################################################
45
46
=head _getBreadcrumbLinks
47
48
@RETURNS List of all breadcrumb links
49
=cut
50
51
sub _getBreadcrumbLinks {
52
    my ($self) = @_;
53
    my $d = $self->getDriver();
54
55
    my $breadcrumbLinks = $d->find_elements("div#breadcrumbs a");
56
    return ($breadcrumbLinks);
57
}
58
59
=head _getHeaderElements
60
61
@RETURNS HASHRef of all the Intranet header clickables.
62
=cut
63
64
sub _getHeaderElements {
65
    my ($self) = @_;
66
    my $d = $self->getDriver();
67
68
    my ($patronsA, $searchA, $cartA, $moreA, $drop3A, $helpA);
69
    #Always visible elements
70
    $patronsA = $d->find_element("#header a[href*='members-home.pl']");
71
    $searchA = $d->find_element ("#header a[href*='search.pl']");
72
    $cartA = $d->find_element   ("#header a#cartmenulink");
73
    $moreA = $d->find_element   ("#header a[href='#']");
74
    $drop3A = $d->find_element  ("#header a#drop3");
75
    $helpA = $d->find_element   ("#header a#helper");
76
77
    my $e = {};
78
    $e->{patrons} = $patronsA if $patronsA;
79
    $e->{search} = $searchA if $searchA;
80
    $e->{cart} = $cartA if $cartA;
81
    $e->{more} = $moreA if $moreA;
82
    $e->{drop3} = $drop3A if $drop3A;
83
    $e->{help} = $helpA if $helpA;
84
    return $e;
85
}
86
87
=head _getPasswordLoginElements
88
89
@RETURNS List of Selenium::Remote::Webelement-objects,
90
         ($submitButton, $useridInput, $passwordInput)
91
=cut
92
93
sub _getPasswordLoginElements {
94
    my ($self) = @_;
95
    my $d = $self->getDriver();
96
97
    my $submitButton  = $d->find_element('#submit');
98
    my $useridInput   = $d->find_element('#userid');
99
    my $passwordInput = $d->find_element('#password');
100
    return ($submitButton, $useridInput, $passwordInput);
101
}
102
103
=head _getLoggedInBranchNameElement
104
@RETURNS Selenium::Remote::WebElement matching the <span> containing the currently logged in users branchname
105
=cut
106
107
sub _getLoggedInBranchNameElement {
108
    my ($self) = @_;
109
    my $d = $self->getDriver();
110
    $self->debugTakeSessionSnapshot();
111
112
    my $header = $self->_getHeaderElements();
113
    my $loggedInBranchNameSpan = $d->find_child_element($header->{drop3}, "#logged-in-branch-name", 'css');
114
    return $loggedInBranchNameSpan;
115
}
116
117
=head _getLoggedInBranchCode
118
@RETURNS String, the logged in branch code
119
=cut
120
121
sub _getLoggedInBranchCode {
122
    my ($self) = @_;
123
    my $d = $self->getDriver();
124
    $self->debugTakeSessionSnapshot();
125
126
    #Because the branchcode element is hidden, we need to inject some javascript to get its value since Selenium (t$
127
    my $script = q{
128
        var elem = document.getElementById('logged-in-branch-code').innerHTML;
129
        var callback = arguments[arguments.length-1];
130
        callback(elem);
131
    };
132
    my $loggedInBranchCode = $d->execute_async_script($script);
133
    return $loggedInBranchCode;
134
}
135
136
################################################################################
137
=head PageObject Services
138
139
=cut
140
################################################################################
141
142
=head isPasswordLoginAvailable
143
144
    $page->isPasswordLoginAvailable();
145
146
@RETURN t::lib::Page-object
147
@CROAK if password login is unavailable.
148
=cut
149
150
sub isPasswordLoginAvailable {
151
    my $self = shift;
152
    my $d = $self->getDriver();
153
    $self->debugTakeSessionSnapshot();
154
155
    $self->_getPasswordLoginElements();
156
    ok(($d->get_title() =~ /Log in to Koha/), "Intra PasswordLogin available");
157
    return $self;
158
}
159
160
sub doPasswordLogin {
161
    my ($self, $username, $password) = @_;
162
    my $d = $self->getDriver();
163
    $self->debugTakeSessionSnapshot();
164
165
    my ($submitButton, $useridInput, $passwordInput) = $self->_getPasswordLoginElements();
166
    $useridInput->send_keys($username);
167
    $passwordInput->send_keys($password);
168
    $submitButton->click();
169
    $self->debugTakeSessionSnapshot();
170
171
    my $cookies = $d->get_all_cookies();
172
    my @cgisessid = grep {$_->{name} eq 'CGISESSID'} @$cookies;
173
174
    ok(($d->get_title() !~ /Log in to Koha/ && #No longer in the login page
175
        $d->get_title() !~ /Access denied/ &&
176
        $cgisessid[0]) #Cookie CGISESSID defined!
177
       , "Intra PasswordLogin succeeded");
178
179
    return $self; #After a succesfull password login, we are directed to the same page we tried to access.
180
}
181
182
sub failPasswordLogin {
183
    my ($self, $username, $password) = @_;
184
    my $d = $self->getDriver();
185
    $self->debugTakeSessionSnapshot();
186
187
    my ($submitButton, $useridInput, $passwordInput) = $self->_getPasswordLoginElements();
188
    $useridInput->send_keys($username);
189
    $passwordInput->send_keys($password);
190
    $submitButton->click();
191
    $self->debugTakeSessionSnapshot();
192
193
    my $cookies = $d->get_all_cookies();
194
    my @cgisessid = grep {$_->{name} eq 'CGISESSID'} @$cookies;
195
196
    ok($d->get_title() =~ /Log in to Koha/ #Still in the login page
197
       , "Intra PasswordLogin failed");
198
199
    return $self; #After a successful password login, we are directed to the same page we tried to access.
200
}
201
202
sub doPasswordLogout {
203
    my ($self, $username, $password) = @_;
204
    my $d = $self->getDriver();
205
    $self->debugTakeSessionSnapshot();
206
207
    #Click the dropdown menu to make the logout-link visible
208
    my $logged_in_identifierA = $d->find_element('#drop3'); #What a nice and descriptive HTML element name!
209
    $logged_in_identifierA->click();
210
211
    #Logout
212
    my $logoutA = $d->find_element('#logout');
213
    $logoutA->click();
214
    $self->debugTakeSessionSnapshot();
215
216
    ok(($d->get_title() =~ /Log in to Koha/), "Intra PasswordLogout succeeded");
217
    return $self; #After a succesfull password logout, we are still in the same page we did before logout.
218
}
219
220
sub isLoggedInBranchCode {
221
    my ($self, $expectedBranchCode) = @_;
222
223
    my $loggedInBranchCode = $self->_getLoggedInBranchCode();
224
    is($expectedBranchCode, $loggedInBranchCode, "#logged-in-branch-code '".$loggedInBranchCode."' matches '$expectedBranchCode'");
225
    return $self;
226
}
227
228
1; #Make the compiler happy!
(-)a/t/lib/Page/Mainpage.pm (+64 lines)
Line 0 Link Here
1
package t::lib::Page::Mainpage;
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use base qw(t::lib::Page::Intra);
23
24
=head NAME t::lib::Page::Mainpage
25
26
=head SYNOPSIS
27
28
Mainpage PageObject providing page functionality as a service!
29
30
=cut
31
32
sub new {
33
    my ($class, $params) = @_;
34
    unless (ref($params) eq 'HASH') {
35
        $params = {};
36
    }
37
    $params->{resource} = '/cgi-bin/koha/mainpage.pl';
38
    $params->{type}     = 'staff';
39
    my $self = $class->SUPER::new($params);
40
41
    return $self;
42
}
43
44
################################################################################
45
=head UI Mapping helper subroutines
46
See. Selenium documentation best practices for UI element mapping to common language descriptions.
47
=cut
48
################################################################################
49
50
51
52
53
54
################################################################################
55
=head PageObject Services
56
57
=cut
58
################################################################################
59
60
61
62
63
64
1; #Make the compiler happy!
(-)a/t/lib/Page/Members/ApiKeys.pm (+200 lines)
Line 0 Link Here
1
package t::lib::Page::Members::ApiKeys;
2
3
# Copyright 2015 KohaSuomi!
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Scalar::Util qw(blessed);
22
use Test::More;
23
24
use base qw(t::lib::Page::Intra t::lib::Page::Members::Toolbar);
25
26
use Koha::Exception::BadParameter;
27
use Koha::Exception::UnknownObject;
28
29
=head NAME t::lib::Page::Members::ApiKeys
30
31
=head SYNOPSIS
32
33
apikeys.pl PageObject providing page functionality as a service!
34
35
=cut
36
37
=head new
38
39
    my $apikeys = t::lib::Page::Members::ApiKeys->new({borrowernumber => "1"});
40
41
Instantiates a WebDriver and loads the members/apikeys.pl.
42
@PARAM1 HASHRef of optional and MANDATORY parameters
43
MANDATORY extra parameters:
44
    borrowernumber => loads the page to display Borrower matching the given borrowernumber
45
46
@RETURNS t::lib::Page::Members::ApiKeys, ready for user actions!
47
=cut
48
49
sub new {
50
    my ($class, $params) = @_;
51
    unless (ref($params) eq 'HASH' || (blessed($params) && $params->isa('t::lib::Page') )) {
52
        $params = {};
53
    }
54
    $params->{resource} = '/cgi-bin/koha/members/apikeys.pl';
55
    $params->{type}     = 'staff';
56
57
    $params->{getParams} = [];
58
    #Handle MANDATORY parameters
59
    if ($params->{borrowernumber}) {
60
        push @{$params->{getParams}}, "borrowernumber=".$params->{borrowernumber};
61
    }
62
    else {
63
        Koha::Exception::BadParameter->throw(error => __PACKAGE__."->new():> Parameter 'borrowernumber' is missing.");
64
    }
65
66
    my $self = $class->SUPER::new($params);
67
68
    return $self;
69
}
70
71
################################################################################
72
=head UI Mapping helper subroutines
73
See. Selenium documentation best practices for UI element mapping to common language descriptions.
74
=cut
75
################################################################################
76
77
=head _getActionsAndTableElements
78
@RETURNS List of
79
         HASHRef of Selenium::Driver::Webelement-objects matching the generic
80
                 actions on this page, eg. 'generateNewKey'.
81
         HASHRef of Selenium::Driver::Webelement-objects keyed with the apiKey hash/text.
82
                 These are all the apiKey table rows present, and have the
83
                 elements prefetched for easy access.
84
85
=cut
86
87
sub _getActionsAndTableElements {
88
    my ($self) = @_;
89
    my $d = $self->getDriver();
90
91
    my $generateNewKeySubmit = $d->find_element("#generatenewkey", 'css');
92
93
    my $a = {}; #Collect action elements here
94
    $a->{generateNewKey} = $generateNewKeySubmit; #Bind the global action here for easy reference.
95
96
    my $apiKeyRows;
97
    eval { #We might not have ApiKeys yet.
98
        $apiKeyRows = $d->find_elements("#apikeystable tr", 'css');
99
        shift @$apiKeyRows; #Remove the table header row
100
    };
101
    my %apiKeys;
102
    for(my $i=0 ; $i<scalar(@$apiKeyRows) ; $i++) {
103
        #Iterate every apiKey in the apiKeys table and prefetch the interesting data as text and available action elements.
104
        my $row = $apiKeyRows->[$i];
105
        $row->{'nth-of-type'} = $i+1; #starts from 1
106
        $row->{key} = $d->find_child_element($row, "td.apikeykey", 'css')->get_text();
107
        $row->{active} = $d->find_child_element($row, "td.apikeyactive", 'css')->get_text();
108
        $row->{lastTransaction} = $d->find_child_element($row, "td.apikeylastransaction", 'css')->get_text();
109
        $row->{delete} = $d->find_child_element($row, "input.apikeydelete", 'css');
110
        eval {
111
            $row->{revoke} = $d->find_child_element($row, "input.apikeyrevoke", 'css');
112
        };
113
        eval {
114
            $row->{activate} = $d->find_child_element($row, "input.apikeyactivate", 'css');
115
        };
116
        $apiKeys{$row->{key}} = $row;
117
    }
118
119
    return ($a, \%apiKeys);
120
}
121
122
123
124
################################################################################
125
=head PageObject Services
126
127
=cut
128
################################################################################
129
130
sub generateNewApiKey {
131
    my ($self) = @_;
132
    my $d = $self->getDriver();
133
    $self->debugTakeSessionSnapshot();
134
135
    my ($actionElements, $apiKeyRows) = $self->_getActionsAndTableElements();
136
    my $apiKeyRowsCountPre = (ref $apiKeyRows eq 'HASH') ? scalar(keys(%$apiKeyRows)) : 0;
137
    $actionElements->{generateNewKey}->click();
138
    $self->debugTakeSessionSnapshot();
139
140
    ($actionElements, $apiKeyRows) = $self->_getActionsAndTableElements();
141
    my $apiKeyRowsCountPost = (ref $apiKeyRows eq 'HASH') ? scalar(keys(%$apiKeyRows)) : 0;
142
    is($apiKeyRowsCountPre+1, $apiKeyRowsCountPost, "ApiKey generated");
143
    return $self;
144
}
145
146
sub revokeApiKey {
147
    my ($self, $apiKey) = @_;
148
    my $d = $self->getDriver();
149
    $self->debugTakeSessionSnapshot();
150
151
    my ($actionElements, $apiKeyRows) = $self->_getActionsAndTableElements();
152
    my $apiKeyRow = $apiKeyRows->{$apiKey};
153
    Koha::Exception::UnknownObject->throw(error => __PACKAGE__."revokeApiKey():> No matching apiKey '$apiKey' found.") unless $apiKeyRow;
154
    $apiKeyRow->{revoke}->click();
155
    $self->debugTakeSessionSnapshot();
156
157
    ($actionElements, $apiKeyRows) = $self->_getActionsAndTableElements();
158
    $apiKeyRow = $apiKeyRows->{$apiKey};
159
    Koha::Exception::UnknownObject->throw(error => __PACKAGE__."revokeApiKey():> No matching apiKey '$apiKey' found after revoking it.") unless $apiKeyRow;
160
    is($apiKeyRow->{active}, 'No', "ApiKey revoked");
161
    return $self;
162
}
163
164
sub activateApiKey {
165
    my ($self, $apiKey) = @_;
166
    my $d = $self->getDriver();
167
    $self->debugTakeSessionSnapshot();
168
169
    my ($actionElements, $apiKeyRows) = $self->_getActionsAndTableElements();
170
    my $apiKeyRow = $apiKeyRows->{$apiKey};
171
    Koha::Exception::UnknownObject->throw(error => __PACKAGE__."revokeApiKey():> No matching apiKey '$apiKey' found.") unless $apiKeyRow;
172
    $apiKeyRow->{activate}->click();
173
    $self->debugTakeSessionSnapshot();
174
175
    ($actionElements, $apiKeyRows) = $self->_getActionsAndTableElements();
176
    $apiKeyRow = $apiKeyRows->{$apiKey};
177
    Koha::Exception::UnknownObject->throw(error => __PACKAGE__."revokeApiKey():> No matching apiKey '$apiKey' found after activating it.") unless $apiKeyRow;
178
    is($apiKeyRow->{active}, 'Yes', "ApiKey activated");
179
    return $self;
180
}
181
182
sub deleteApiKey {
183
    my ($self, $apiKey) = @_;
184
    my $d = $self->getDriver();
185
    $self->debugTakeSessionSnapshot();
186
187
    my ($actionElements, $apiKeyRows) = $self->_getActionsAndTableElements();
188
    my $apiKeyRowsCountPre = (ref $apiKeyRows eq 'HASH') ? scalar(keys(%$apiKeyRows)) : 0;
189
    my $apiKeyRow = $apiKeyRows->{$apiKey};
190
    Koha::Exception::UnknownObject->throw(error => __PACKAGE__."revokeApiKey():> No matching apiKey '$apiKey' found.") unless $apiKeyRow;
191
    $apiKeyRow->{delete}->click();
192
    $self->debugTakeSessionSnapshot();
193
194
    ($actionElements, $apiKeyRows) = $self->_getActionsAndTableElements();
195
    my $apiKeyRowsCountPost = (ref $apiKeyRows eq 'HASH') ? scalar(keys(%$apiKeyRows)) : 0;
196
    is($apiKeyRowsCountPre-1, $apiKeyRowsCountPost, "ApiKey deleted");
197
    return $self;
198
}
199
200
1; #Make the compiler happy!
(-)a/t/lib/Page/Members/Boraccount.pm (+164 lines)
Line 0 Link Here
1
package t::lib::Page::Members::Boraccount;
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Scalar::Util qw(blessed);
22
use Test::More;
23
24
use base qw(t::lib::Page::Intra t::lib::Page::Members::Toolbar t::lib::Page::Members::LeftNavigation);
25
26
use t::lib::Page::Members::ApiKeys;
27
28
use Koha::Exception::BadParameter;
29
30
=head NAME t::lib::Page::Members::Boraccount
31
32
=head SYNOPSIS
33
34
boraccount.pl PageObject providing page functionality as a service!
35
36
=cut
37
38
=head new
39
40
    my $boraccount = t::lib::Page::Members::Boraccount->new({borrowernumber => "1"});
41
42
Instantiates a WebDriver and loads the members/boraccount.pl.
43
@PARAM1 HASHRef of optional and MANDATORY parameters
44
MANDATORY extra parameters:
45
    borrowernumber => loads the page to display Borrower matching the given borrowernumber
46
47
@RETURNS t::lib::Page::Members::Boraccount, ready for user actions!
48
=cut
49
50
sub new {
51
    my ($class, $params) = @_;
52
    unless (ref($params) eq 'HASH' || (blessed($params) && $params->isa('t::lib::Page') )) {
53
        $params = {};
54
    }
55
    $params->{resource} = '/cgi-bin/koha/members/boraccount.pl';
56
    $params->{type}     = 'staff';
57
58
    $params->{getParams} = [];
59
    #Handle MANDATORY parameters
60
    if ($params->{borrowernumber}) {
61
        push @{$params->{getParams}}, "borrowernumber=".$params->{borrowernumber};
62
    }
63
    else {
64
        Koha::Exception::BadParameter->throw(error => __PACKAGE__."->new():> Parameter 'borrowernumber' is missing.");
65
    }
66
67
    my $self = $class->SUPER::new($params);
68
69
    return $self;
70
}
71
72
################################################################################
73
=head UI Mapping helper subroutines
74
See. Selenium documentation best practices for UI element mapping to common language descriptions.
75
=cut
76
################################################################################
77
78
sub navigateToPayFinesTab {
79
    my ($self) = @_;
80
    my $d = $self->getDriver();
81
    $self->debugTakeSessionSnapshot();
82
83
    my $tab = $d->find_element("div.statictabs ul li a[href*='pay.pl?borrowernumber=']", 'css');
84
    $tab->click();
85
    ok($d->get_title() =~ m/Pay Fines for/, "Intra Navigate to Pay fines tab");
86
87
    $self->debugTakeSessionSnapshot();
88
89
    return t::lib::Page::Members::Pay->rebrandFromPageObject($self);
90
}
91
92
sub findFine {
93
    my ($self, $note) = @_;
94
    my $d = $self->getDriver();
95
    $self->debugTakeSessionSnapshot();
96
97
    my $payment_note = $d->find_element("//td[text() = \"".$note."\"]", "xpath");
98
99
    ok(1, "Intra Found payment with note ".$note);
100
101
    return $self;
102
}
103
104
sub isFinePaid {
105
    my ($self, $note, $noteColumnIndex, $amountOutstandingColumnIndex) = @_;
106
107
    return isFineAmountOutstanding($self, $note, "0.00", $noteColumnIndex, $amountOutstandingColumnIndex);
108
}
109
110
sub isFineAmount {
111
    my ($self, $note, $amount, $noteColumnIndex, $amountColumnIndex) = @_;
112
    my $d = $self->getDriver();
113
    $self->debugTakeSessionSnapshot();
114
115
    $noteColumnIndex = 3 if not defined $noteColumnIndex;
116
    $amountColumnIndex = 4 if not defined $amountColumnIndex;
117
118
    # If POS integration is enabled, add 1 to index (because of column "transaction id")
119
    if (C4::Context->preference("POSIntegration") ne "OFF") {
120
        $noteColumnIndex++;
121
        $amountColumnIndex++;
122
    }
123
124
    my $fine = $d->find_element("//tr[(td[".$noteColumnIndex."][text()=\"".$note."\"]) and (td[".$amountColumnIndex."][text()=\"".$amount."\"])]", "xpath");
125
126
    ok(1, "Intra Found payment with note ".$note." and amount ".$amount);
127
128
    return $self;
129
}
130
131
sub isFineAmountOutstanding {
132
    my ($self, $note, $amountOutstanding, $noteColumnIndex, $amountOutstandingColumnIndex) = @_;
133
    my $d = $self->getDriver();
134
    $self->debugTakeSessionSnapshot();
135
136
    $noteColumnIndex = 3 if not defined $noteColumnIndex;
137
    $amountOutstandingColumnIndex = 5 if not defined $amountOutstandingColumnIndex;
138
139
    # If POS integration is enabled, add 1 to index (because of column "transaction id")
140
    if (C4::Context->preference("POSIntegration") ne "OFF") {
141
        $noteColumnIndex++;
142
        $amountOutstandingColumnIndex++;
143
    }
144
145
    my $fine = $d->find_element("//tr[(td[".$noteColumnIndex."][text()=\"".$note."\"]) and (td[".$amountOutstandingColumnIndex."][text()=\"".$amountOutstanding."\"])]", "xpath");
146
147
    ok(1, "Intra Found payment with note ".$note." and amountoutstanding ".$amountOutstanding);
148
149
    return $self;
150
}
151
152
sub isTransactionComplete {
153
    my ($self, $transactionnumber) = @_;
154
    my $d = $self->getDriver();
155
    $self->debugTakeSessionSnapshot();
156
157
    my $transaction_columns = $d->find_element("//td[contains(\@class, 'transactionnumber') and text() = '".$transactionnumber."']", "xpath");
158
159
    ok(1, "Intra Found transaction, number ".$transactionnumber);
160
161
    return $self;
162
}
163
164
1; #Make the compiler happy!
(-)a/t/lib/Page/Members/LeftNavigation.pm (+138 lines)
Line 0 Link Here
1
package t::lib::Page::Members::LeftNavigation;
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Scalar::Util qw(blessed);
22
use Test::More;
23
24
=head NAME t::lib::Page::Members::LeftNavigation
25
26
=head SYNOPSIS
27
28
Provides the services of the members/circulation left navigation column/frame for the implementing PageObject
29
30
=cut
31
32
################################################################################
33
=head UI Mapping helper subroutines
34
See. Selenium documentation best practices for UI element mapping to common language descriptions.
35
=cut
36
################################################################################
37
38
=head _getLeftNavigationActionElements
39
@RETURNS HASHRef of Selenium::Driver::Webelements matching all the clickable elements
40
                 in the left navigation frame/column at members and circulation pages.
41
=cut
42
43
sub _getLeftNavigationActionElements {
44
    my ($self) = @_;
45
    my $d = $self->getDriver();
46
47
    my $e = {};
48
    eval {
49
        $e->{checkOut} = $d->find_element("div#menu a[href*='circ/circulation.pl']", 'css');
50
    };
51
    eval {
52
        $e->{details}   = $d->find_element("div#menu a[href*='members/moremember.pl']", 'css');
53
    };
54
    eval {
55
        $e->{fines} = $d->find_element("div#menu a[href*='members/pay.pl']", 'css');
56
    };
57
    eval {
58
        $e->{routingLists}    = $d->find_element("div#menu a[href*='members/routing-lists.pl']", 'css');
59
    };
60
    eval {
61
        $e->{circulationHistory} = $d->find_element("div#menu a[href*='members/readingrec.pl']", 'css');
62
    };
63
    eval {
64
        $e->{modificationLog} = $d->find_element("div#menu a[href*='tools/viewlog.pl']", 'css');
65
    };
66
    eval {
67
        $e->{notices} = $d->find_element("div#menu a[href*='members/notices.pl']", 'css');
68
    };
69
    eval {
70
        $e->{statistics} = $d->find_element("div#menu a[href*='members/statistics.pl']", 'css');
71
    };
72
    eval {
73
        $e->{purchaseSuggestions} = $d->find_element("div#menu a[href*='members/purchase-suggestions.pl']", 'css');
74
    };
75
    return $e;
76
}
77
78
79
80
################################################################################
81
=head PageObject Services
82
83
=cut
84
################################################################################
85
86
sub navigateCheckout {
87
    my ($self) = @_;
88
    my $d = $self->getDriver();
89
    $self->debugTakeSessionSnapshot();
90
91
    my $elements = $self->_getLeftNavigationActionElements();
92
    $elements->{checkOut}->click();
93
    $self->debugTakeSessionSnapshot();
94
95
    ok($d->get_title() =~ m/Checking out to/i,
96
       "Intra Navigate to Check out");
97
98
    return t::lib::Page::Circulation::Circulation->rebrandFromPageObject($self);
99
}
100
101
sub navigateToDetails {
102
    my ($self) = @_;
103
    my $d = $self->getDriver();
104
    $self->debugTakeSessionSnapshot();
105
106
    my $elements = $self->_getLeftNavigationActionElements();
107
    $elements->{details}->click();
108
    $self->debugTakeSessionSnapshot();
109
110
    ok($d->get_title() =~ m/Patron details for/i,
111
       "Intra Navigate to Details");
112
113
    return t::lib::Page::Members::Moremember->rebrandFromPageObject($self);
114
}
115
116
sub navigateToNotices {
117
    my ($self) = @_;
118
    my $d = $self->getDriver();
119
    $self->debugTakeSessionSnapshot();
120
121
    my $elements = $self->_getLeftNavigationActionElements();
122
    my $func = sub {
123
        $elements->{notices}->click();
124
    };
125
    my $success = sub {
126
        return $self->getDriver()->get_title() =~ m/Sent notices/;
127
    };
128
129
    $self->poll($func, $success, 20, 50);
130
    $self->debugTakeSessionSnapshot();
131
132
    ok($d->get_title() =~ m/Sent notices/i,
133
       "Intra Navigate to Notices");
134
135
    return t::lib::Page::Members::Notices->rebrandFromPageObject($self);
136
}
137
138
1; #Make the compiler happy!
(-)a/t/lib/Page/Members/MemberFlags.pm (+143 lines)
Line 0 Link Here
1
package t::lib::Page::Members::MemberFlags;
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Test::More;
22
23
use t::lib::Page::Members::Moremember;
24
25
use base qw(t::lib::Page::Intra t::lib::Page::Members::Toolbar);
26
27
=head NAME t::lib::Page::Members::MemberFlags
28
29
=head SYNOPSIS
30
31
member-flags.pl PageObject providing page functionality as a service!
32
33
=cut
34
35
=head new
36
37
    my $memberflags = t::lib::Page::Members::MemberFlags->new({borrowernumber => "1"});
38
39
Instantiates a WebDriver and loads the members/member-flags.pl.
40
@PARAM1 HASHRef of optional and MANDATORY parameters
41
MANDATORY extra parameters:
42
    borrowernumber => loads the page to display Borrower matching the given borrowernumber
43
44
@RETURNS t::lib::Page::Members::MemberFlags, ready for user actions!
45
=cut
46
47
sub new {
48
    my ($class, $params) = @_;
49
    unless (ref($params) eq 'HASH') {
50
        $params = {};
51
    }
52
    $params->{resource} = '/cgi-bin/koha/members/member-flags.pl';
53
    $params->{type}     = 'staff';
54
55
    $params->{getParams} = [];
56
    #Handle MANDATORY parameters
57
    if ($params->{borrowernumber}) {
58
        push @{$params->{getParams}}, "member=".$params->{borrowernumber};
59
    }
60
    else {
61
        Koha::Exception::BadParameter->throw(error => __PACKAGE__."->new():> Parameter 'borrowernumber' is missing.");
62
    }
63
64
    my $self = $class->SUPER::new($params);
65
66
    return $self;
67
}
68
69
################################################################################
70
=head UI Mapping helper subroutines
71
See. Selenium documentation best practices for UI element mapping to common language descriptions.
72
=cut
73
################################################################################
74
75
sub _getPermissionTreeControlElements {
76
    my ($self) = @_;
77
    my $d = $self->getDriver();
78
79
    my $saveButton   = $d->find_element('input[value="Save"]');
80
    my $cancelButton = $d->find_element('a.cancel');
81
    return ($saveButton, $cancelButton);
82
}
83
84
=head _getPermissionTreePermissionElements
85
86
@PARAM1 Scalar, Koha::Auth::PermissionModule's module
87
@PARAM2 Scalar, Koha::Auth::Permission's code
88
=cut
89
90
sub _getPermissionTreePermissionElements {
91
    my ($self, $module, $code) = @_;
92
    my $d = $self->getDriver();
93
94
    my $moduleTreeExpansionButton = $d->find_element("div.$module-hitarea");
95
    my $moduleCheckbox   = $d->find_element("input#flag-$module");
96
    my $permissionCheckbox = $d->find_element('input#'.$module.'_'.$code);
97
    return ($moduleTreeExpansionButton, $moduleCheckbox, $permissionCheckbox);
98
}
99
100
101
102
################################################################################
103
=head PageObject Services
104
105
=cut
106
################################################################################
107
108
sub togglePermission {
109
    my ($self, $permissionModule, $permissionCode) = @_;
110
    my $d = $self->getDriver();
111
    $self->debugTakeSessionSnapshot();
112
113
    my ($moduleTreeExpansionButton, $moduleCheckbox, $permissionCheckbox) = $self->_getPermissionTreePermissionElements($permissionModule, $permissionCode);
114
    if ($moduleTreeExpansionButton->get_attribute("class") =~ /expandable-hitarea/) { #Permission checkboxes are hidden and need to be shown.
115
        $moduleTreeExpansionButton->click();
116
        $d->pause( $self->{userInteractionDelay} );
117
    }
118
119
120
    #$moduleCheckbox->click(); #Clicking this will toggle all module permissions.
121
    my $checked = $permissionCheckbox->get_attribute("checked") || ''; #Returns undef if not checked
122
    $permissionCheckbox->click();
123
    ok($checked ne ($permissionCheckbox->get_attribute("checked") || ''),
124
       "Module '$permissionModule', permission '$permissionCode', checkbox toggled");
125
    $self->debugTakeSessionSnapshot();
126
127
    return $self;
128
}
129
130
sub submitPermissionTree {
131
    my $self = shift;
132
    my $d = $self->getDriver();
133
134
    my ($submitButton, $cancelButton) = $self->_getPermissionTreeControlElements();
135
    $submitButton->click();
136
    $self->debugTakeSessionSnapshot();
137
138
    ok(($d->get_title() =~ /Patron details for/), "Permissions set");
139
140
    return t::lib::Page::Members::Moremember->rebrandFromPageObject($self);
141
}
142
143
1; #Make the compiler happy!
(-)a/t/lib/Page/Members/Memberentry.pm (+265 lines)
Line 0 Link Here
1
package t::lib::Page::Members::Memberentry;
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Scalar::Util qw(blessed);
22
use Test::More;
23
24
use base qw(t::lib::Page::Intra t::lib::Page::Members::Toolbar t::lib::Page::Members::LeftNavigation);
25
26
use Koha::Exception::BadParameter;
27
28
use t::lib::Page::Circulation::Circulation;
29
30
31
sub new {
32
    my ($class, $params) = @_;
33
    unless (ref($params) eq 'HASH' || (blessed($params) && $params->isa('t::lib::Page') )) {
34
        $params = {};
35
    }
36
    $params->{resource} = '/cgi-bin/koha/members/memberentry.pl';
37
    $params->{type}     = 'staff';
38
39
    $params->{getParams} = [];
40
    #Handle MANDATORY parameters
41
    if ($params->{borrowernumber}) {
42
        push @{$params->{getParams}}, "borrowernumber=".$params->{borrowernumber};
43
    }
44
    else {
45
        Koha::Exception::BadParameter->throw(error => __PACKAGE__."->new():> Parameter 'borrowernumber' is missing.");
46
    }
47
    push @{$params->{getParams}}, "destination=".$params->{destination} if $params->{destination};
48
    push @{$params->{getParams}}, "op=".$params->{op} if $params->{op};
49
    push @{$params->{getParams}}, "categorycode=".$params->{categorycode} if $params->{categorycode};
50
    my $self = $class->SUPER::new($params);
51
52
    return $self;
53
}
54
55
################################################################################
56
=head UI Mapping helper subroutines
57
See. Selenium documentation best practices for UI element mapping to common language descriptions.
58
=cut
59
################################################################################
60
61
62
sub _getInputFieldsForValidation {
63
    my ($self) = @_;
64
    my $d = $self->getDriver();
65
66
    my ($emailInput, $emailProInput, $email_BInput, $phoneInput, $phoneProInput, $phone_BInput, $SMSnumber);
67
    eval {
68
        $emailInput  = $d->find_element('#email');
69
    };
70
    eval {
71
        $emailProInput  = $d->find_element('#emailpro');
72
    };
73
    eval {
74
        $email_BInput  = $d->find_element('#B_email');
75
    };
76
    eval {
77
        $phoneInput  = $d->find_element('#phone');
78
    };
79
    eval {
80
        $phoneProInput  = $d->find_element('#phonepro');
81
    };
82
    eval {
83
        $phone_BInput  = $d->find_element('#B_phone');
84
    };
85
    eval {
86
        $SMSnumber = $d->find_element('#SMSnumber');
87
    };
88
89
    return ($emailInput, $emailProInput, $email_BInput, $phoneInput, $phoneProInput, $phone_BInput, $SMSnumber);
90
}
91
92
sub _getMessagingPreferenceCheckboxes {
93
    my ($self) = @_;
94
    my $d = $self->getDriver();
95
96
    my @email_prefs = $d->find_elements('input[type="checkbox"][id^="email"]');
97
    my @phone_prefs = $d->find_elements('input[type="checkbox"][id^="phone"]');
98
    my @sms_prefs = $d->find_elements('input[type="checkbox"][id^="sms"]');
99
100
    return  { email => \@email_prefs, phone => \@phone_prefs, sms => \@sms_prefs };
101
}
102
103
104
################################################################################
105
=head PageObject Services
106
107
=cut
108
################################################################################
109
110
sub checkMessagingPreferencesSet {
111
    my ($self, $valid, @prefs) = @_;
112
    my $d = $self->getDriver();
113
    $self->debugTakeSessionSnapshot();
114
115
    foreach my $type (@prefs){
116
        my @this_pref = $d->find_elements('input[type="checkbox"][id^="'.$type.'"]');
117
118
        my $ok = 0;
119
120
        foreach my $checkbox (@this_pref){
121
            ok(0, "Intra Memberentry $type messaging checkbox ".$checkbox->get_attribute('id')." not checked") if !$checkbox->is_selected() and $valid;
122
            ok(0, "Intra Memberentry $type messaging checkbox ".$checkbox->get_attribute('id')." checked (not supposed to be)") if $checkbox->is_selected() and !$valid;
123
            $ok = 1;
124
        }
125
        ok($ok, "Intra Memberentry $type messaging checkboxes ok (all " . (($valid) ? 'checked':'unchecked') . ")");
126
    }
127
128
    return $self;
129
}
130
131
sub clearMessagingContactFields {
132
    my ($self, @fields) = @_;
133
    my $d = $self->getDriver();
134
    $self->debugTakeSessionSnapshot();
135
136
    my ($emailInput, $emailProInput, $email_BInput, $phoneInput, $phoneProInput, $phone_BInput, $SMSnumber) = $self->_getInputFieldsForValidation();
137
138
    if (@fields) {
139
        for my $field (@fields){
140
            $emailInput->clear() if $field eq "email";
141
            $emailProInput->clear() if $field eq "emailpro";
142
            $email_BInput->clear() if $field eq "B_email";
143
            $phoneInput->clear() if $field eq "phone";
144
            $phoneProInput->clear() if $field eq "phonepro";
145
            $phone_BInput->clear() if $field eq "B_phone";
146
            $SMSnumber->clear() if $field eq "SMSnumber";
147
        }
148
        ok(1, "Intra Memberentry contact fields (@fields) cleared");
149
    } else {
150
        $emailInput->clear();
151
        $emailProInput->clear();
152
        $email_BInput->clear();
153
        $phoneInput->clear();
154
        $phoneProInput->clear();
155
        $phone_BInput->clear();
156
        $SMSnumber->clear();
157
        ok(1, "Intra Memberentry contact fields (email, emailpro, email_B, phone, phonepro, phone_B, SMSnumber) cleared");
158
    }
159
160
    return $self;
161
}
162
163
sub checkPreferences {
164
    my ($self, $valid, $type) = @_;
165
    my $d = $self->getDriver();
166
    $self->debugTakeSessionSnapshot();
167
168
    my $checkboxes = $self->_getMessagingPreferenceCheckboxes();
169
170
    ok (0, "Intra $type checkboxes not defined") if not defined $checkboxes->{$type};
171
    return 0 if not defined $checkboxes->{$type};
172
173
    foreach my $checkbox (@{ $checkboxes->{$type} }){
174
        ok(0, "Intra Memberentry $type messaging checkbox ".$checkbox->get_attribute('id')." not available") if !$checkbox->is_enabled() and $valid;
175
        ok(0, "Intra Memberentry $type messaging checkbox ".$checkbox->get_attribute('id')." available (not supposed to be)") if $checkbox->is_enabled() and !$valid;
176
177
        $checkbox->click() if not $checkbox->is_selected();
178
    }
179
    ok (1, "Intra Memberentry $type messaging checkboxes checked") if $valid;
180
181
    return $self;
182
}
183
sub setEmail {
184
    my ($self, $input) = @_;
185
    my $d = $self->getDriver();
186
    $self->debugTakeSessionSnapshot();
187
188
    my ($emailInput, $emailProInput, $email_BInput, $phoneInput, $phoneProInput, $phone_BInput, $SMSnumber) = $self->_getInputFieldsForValidation();
189
190
    $emailInput->clear();
191
    $emailProInput->clear();
192
    $email_BInput->clear();
193
    $emailInput->send_keys($input);
194
    $emailProInput->send_keys($input);
195
    $email_BInput->send_keys($input);
196
    ok(1, "Intra Memberentry Wrote \"$input\" to email fields.");
197
198
    return $self;
199
}
200
201
sub setPhone {
202
    my ($self, $input) = @_;
203
    my $d = $self->getDriver();
204
    $self->debugTakeSessionSnapshot();
205
206
    my ($emailInput, $emailProInput, $email_BInput, $phoneInput, $phoneProInput, $phone_BInput, $SMSnumber) = $self->_getInputFieldsForValidation();
207
208
    $phoneInput->clear();
209
    $phoneProInput->clear();
210
    $phone_BInput->clear();
211
    $phoneInput->send_keys($input);
212
    $phoneProInput->send_keys($input);
213
    $phone_BInput->send_keys($input);
214
    ok(1, "Intra Memberentry Wrote \"$input\" to phone fields.");
215
216
    return $self;
217
}
218
219
sub setSMSNumber {
220
    my ($self, $input) = @_;
221
    my $d = $self->getDriver();
222
    $self->debugTakeSessionSnapshot();
223
224
    my ($emailInput, $emailProInput, $email_BInput, $phoneInput, $phoneProInput, $phone_BInput, $SMSnumber) = $self->_getInputFieldsForValidation();
225
226
    $SMSnumber->clear();
227
    $SMSnumber->send_keys($input);
228
    ok(1, "Intra Memberentry Wrote \"$input\" to SMSnumber.");
229
230
    return $self;
231
}
232
233
sub submitForm {
234
    my ($self, $valid) = @_;
235
    my $d = $self->getDriver();
236
    $self->debugTakeSessionSnapshot();
237
238
    eval {
239
        my $holdsIdentifier = $d->find_element('#othernames');
240
        $holdsIdentifier->click();
241
    };
242
    my $submitButton = $d->find_element('#saverecord');
243
    $submitButton->click();
244
    $self->debugTakeSessionSnapshot();
245
246
    if ($valid) {
247
        my $submitted = $d->find_element("#editpatron", 'css');
248
        ok(1, "Intra Memberentry Submit changes success");
249
        return t::lib::Page::Circulation::Circulation->rebrandFromPageObject($self);
250
    } else {
251
        my @notsubmitted = $d->find_elements('form#entryform label[class="error"]', 'css');
252
        my $error_ids = "";
253
254
        foreach my $el_id (@notsubmitted){
255
            my $attr_id = $el_id->get_attribute("for");
256
            $error_ids .=  "'".$attr_id . "' ";
257
        }
258
259
        ok(1, "Intra Memberentry Submit changes ". $error_ids .", validation error (as expected).");
260
        $d->refresh();
261
        return $self;
262
    }
263
}
264
265
1;
(-)a/t/lib/Page/Members/Moremember.pm (+207 lines)
Line 0 Link Here
1
package t::lib::Page::Members::Moremember;
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Scalar::Util qw(blessed);
22
use Test::More;
23
24
use base qw(t::lib::Page::Intra t::lib::Page::Members::Toolbar t::lib::Page::Members::LeftNavigation);
25
26
use t::lib::Page::Members::ApiKeys;
27
28
use Koha::Exception::BadParameter;
29
30
=head NAME t::lib::Page::Members::Moremember
31
32
=head SYNOPSIS
33
34
moremember.pl PageObject providing page functionality as a service!
35
36
=cut
37
38
=head new
39
40
    my $moremember = t::lib::Page::Members::Moremember->new({borrowernumber => "1"});
41
42
Instantiates a WebDriver and loads the members/moremember.pl.
43
@PARAM1 HASHRef of optional and MANDATORY parameters
44
MANDATORY extra parameters:
45
    borrowernumber => loads the page to display Borrower matching the given borrowernumber
46
47
@RETURNS t::lib::Page::Members::Moremember, ready for user actions!
48
=cut
49
50
sub new {
51
    my ($class, $params) = @_;
52
    unless (ref($params) eq 'HASH' || (blessed($params) && $params->isa('t::lib::Page') )) {
53
        $params = {};
54
    }
55
    $params->{resource} = '/cgi-bin/koha/members/moremember.pl';
56
    $params->{type}     = 'staff';
57
58
    $params->{getParams} = [];
59
    #Handle MANDATORY parameters
60
    if ($params->{borrowernumber}) {
61
        push @{$params->{getParams}}, "borrowernumber=".$params->{borrowernumber};
62
    }
63
    else {
64
        Koha::Exception::BadParameter->throw(error => __PACKAGE__."->new():> Parameter 'borrowernumber' is missing.");
65
    }
66
67
    my $self = $class->SUPER::new($params);
68
69
    return $self;
70
}
71
72
################################################################################
73
=head UI Mapping helper subroutines
74
See. Selenium documentation best practices for UI element mapping to common language descriptions.
75
=cut
76
################################################################################
77
78
sub _getEditLinks {
79
    my ($self) = @_;
80
    my $d = $self->getDriver();
81
82
    my $patron_info_edit = $d->find_element("div#patron-information div.action a[href*='memberentry.pl?op=modify'][href*='step=1']", 'css');
83
    my $sms_number_edit = $d->find_element("div.action a[href*='memberentry.pl?op=modify'][href*='step=5']", 'css');
84
    my $library_use_edit = $d->find_element("div.action a[href*='memberentry.pl?op=modify'][href*='step=3']", 'css');
85
    my $alternate_addr_edit = $d->find_element("div.action a[href*='memberentry.pl?op=modify'][href*='step=6']", 'css');
86
    my $alternative_contact_edit = $d->find_element("div.action a[href*='memberentry.pl?op=modify'][href*='step=2']", 'css');
87
88
    my $e = {};
89
    $e->{patron_information} = $patron_info_edit if $patron_info_edit;
90
    $e->{smsnumber} = $sms_number_edit if $sms_number_edit;
91
    $e->{library_use} = $library_use_edit if $library_use_edit;
92
    $e->{alternate_address} = $alternate_addr_edit if $alternate_addr_edit;
93
    $e->{alternative_contact} = $alternative_contact_edit if $alternative_contact_edit;
94
    return $e;
95
}
96
97
sub _getMessagingPreferenceCheckboxes {
98
    my ($self) = @_;
99
    my $d = $self->getDriver();
100
101
    my @email_prefs = $d->find_elements('input[type="checkbox"][id^="email"]');
102
    my @phone_prefs = $d->find_elements('input[type="checkbox"][id^="phone"]');
103
    my @sms_prefs = $d->find_elements('input[type="checkbox"][id^="sms"]');
104
105
    return  { email => \@email_prefs, phone => \@phone_prefs, sms => \@sms_prefs };
106
}
107
108
################################################################################
109
=head PageObject Services
110
111
=cut
112
################################################################################
113
114
sub checkMessagingPreferencesSet {
115
    my ($self, $valid, @prefs) = @_;
116
    my $d = $self->getDriver();
117
    $self->debugTakeSessionSnapshot();
118
119
    foreach my $type (@prefs){
120
        my @this_pref = $d->find_elements('input[type="checkbox"][id^="'.$type.'"]');
121
122
        my $ok = 0;
123
124
        foreach my $checkbox (@this_pref){
125
            ok(0, "Intra Moremember $type messaging checkbox ".$checkbox->get_attribute('id')." not checked") if !$checkbox->is_selected() and $valid;
126
            ok(0, "Intra Moremember $type messaging checkbox ".$checkbox->get_attribute('id')." checked (not supposed to be)") if $checkbox->is_selected() and !$valid;
127
            $ok = 1;
128
        }
129
        ok($ok, "Intra Moremember $type messaging checkboxes ok (all " . (($valid) ? 'checked':'unchecked') . ")");
130
    }
131
132
    return $self;
133
}
134
135
sub navigateToPatronInformationEdit {
136
    my ($self) = @_;
137
    my $d = $self->getDriver();
138
    $self->debugTakeSessionSnapshot();
139
140
    my $elements = $self->_getEditLinks();
141
    $elements->{patron_information}->click();
142
    ok($d->get_title() =~ m/Modify(.*)patron/, "Intra Navigate to Modify patron information");
143
144
    $self->debugTakeSessionSnapshot();
145
146
    return t::lib::Page::Members::Memberentry->rebrandFromPageObject($self);
147
}
148
149
sub navigateToSMSnumberEdit {
150
    my ($self) = @_;
151
    my $d = $self->getDriver();
152
    $self->debugTakeSessionSnapshot();
153
154
    my $elements = $self->_getEditLinks();
155
    $elements->{smsnumber}->click();
156
    ok($d->get_title() =~ m/Modify(.*)patron/, "Intra Navigate to Modify patron SMS number");
157
158
    $self->debugTakeSessionSnapshot();
159
160
    return t::lib::Page::Members::Memberentry->rebrandFromPageObject($self);
161
}
162
163
sub navigateToLibraryUseEdit {
164
    my ($self) = @_;
165
    my $d = $self->getDriver();
166
    $self->debugTakeSessionSnapshot();
167
168
    my $elements = $self->_getEditLinks();
169
    $elements->{library_use}->click();
170
    ok($d->get_title() =~ m/Modify(.*)patron/, "Intra Navigate to Modify patron Library use");
171
172
    $self->debugTakeSessionSnapshot();
173
174
    return t::lib::Page::Members::Memberentry->rebrandFromPageObject($self);
175
}
176
177
sub navigateToAlternateAddressEdit {
178
    my ($self) = @_;
179
    my $d = $self->getDriver();
180
    $self->debugTakeSessionSnapshot();
181
182
    my $elements = $self->_getEditLinks();
183
    $elements->{alternate_address}->click();
184
    ok($d->get_title() =~ m/Modify(.*)patron/, "Intra Navigate to Modify patron Alternate address");
185
186
    $self->debugTakeSessionSnapshot();
187
188
    return t::lib::Page::Members::Memberentry->rebrandFromPageObject($self);
189
}
190
191
sub navigateToAlternativeContactEdit {
192
    my ($self) = @_;
193
    my $d = $self->getDriver();
194
    $self->debugTakeSessionSnapshot();
195
196
    my $elements = $self->_getEditLinks();
197
    $elements->{alternative_contact}->click();
198
    ok($d->get_title() =~ m/Modify(.*)patron/, "Intra Navigate to Modify patron Alternative contact");
199
200
    $self->debugTakeSessionSnapshot();
201
202
    return t::lib::Page::Members::Memberentry->rebrandFromPageObject($self);
203
}
204
205
206
207
1; #Make the compiler happy!
(-)a/t/lib/Page/Members/Notices.pm (+195 lines)
Line 0 Link Here
1
package t::lib::Page::Members::Notices;
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Scalar::Util qw(blessed);
22
use Test::More;
23
24
use base qw(t::lib::Page::Intra t::lib::Page::Members::Toolbar t::lib::Page::Members::LeftNavigation);
25
26
use Koha::Exception::BadParameter;
27
28
use t::lib::Page::Circulation::Circulation;
29
30
31
sub new {
32
    my ($class, $params) = @_;
33
    unless (ref($params) eq 'HASH' || (blessed($params) && $params->isa('t::lib::Page') )) {
34
        $params = {};
35
    }
36
    $params->{resource} = '/cgi-bin/koha/members/notices.pl';
37
    $params->{type}     = 'staff';
38
39
    $params->{getParams} = [];
40
    #Handle MANDATORY parameters
41
    if ($params->{borrowernumber}) {
42
        push @{$params->{getParams}}, "borrowernumber=".$params->{borrowernumber};
43
    }
44
    else {
45
        Koha::Exception::BadParameter->throw(error => __PACKAGE__."->new():> Parameter 'borrowernumber' is missing.");
46
    }
47
    my $self = $class->SUPER::new($params);
48
49
    return $self;
50
}
51
52
################################################################################
53
=head UI Mapping helper subroutines
54
See. Selenium documentation best practices for UI element mapping to common language descriptions.
55
=cut
56
################################################################################
57
58
sub _getNoticesTable {
59
    my ($self) = @_;
60
    my $d = $self->getDriver();
61
62
    my $e = {};
63
64
    eval {
65
        $e->{noticestable_headers} = $d->find_elements("#noticestable th", 'css');
66
    };
67
    eval {
68
        $e->{noticestable_cells} = $d->find_elements("#noticestable td", 'css');
69
    };
70
    eval {
71
        $e->{noticestable_rows} = $d->find_elements("#noticestable tr", 'css');
72
    };
73
74
    return $e;
75
}
76
77
################################################################################
78
=head PageObject Services
79
80
=cut
81
################################################################################
82
83
84
# column and row first index is 1
85
sub getTextInColumnAtRow {
86
    my ($self, $searchText, $params) = @_;
87
    my $d = $self->getDriver();
88
    $self->debugTakeSessionSnapshot();
89
90
    if (not exists $params->{column} or not exists $params->{row} or
91
        not $params->{column} or not $params->{row}) {
92
        warn "t::lib::Page::Members::Notices->getColumnAtRow must be called with column and row numbers, e.g. {column => 1, row=1}";
93
    }
94
95
    my $col = $params->{column};
96
    my $row = $params->{row};
97
98
    my $cell = $d->find_element("#noticestable tr:nth-child($row) td:nth-child($col)");
99
100
    ok(($cell->get_text() =~ /^(.*)$searchText(.*)$/), "Intra Notices Text \"$searchText\" found at column ".
101
       $params->{column}." row ".$params->{row}." matches \"".$cell->get_text()."\".");
102
103
    return $self;
104
}
105
106
sub hasDeliveryNoteColumnInNoticesTable {
107
    my ($self) = @_;
108
    my $d = $self->getDriver();
109
    $self->debugTakeSessionSnapshot();
110
111
    my $elements = $self->_getNoticesTable();
112
113
    my $headers = $elements->{noticestable_headers};
114
115
    my $hasDeliveryNote = 0;
116
117
    foreach my $header(@$headers){
118
        $hasDeliveryNote = 1 if ($header->get_text() =~ /^Delivery note$/);
119
    }
120
121
    ok($hasDeliveryNote, "Intra Notices Table has all headings");
122
123
    return $self;
124
}
125
126
sub hasTextInTableCell {
127
    my ($self, $txt) = @_;
128
    my $d = $self->getDriver();
129
    $self->debugTakeSessionSnapshot();
130
131
    my $elements = $self->_getNoticesTable();
132
133
    my $cells = $elements->{noticestable_cells};
134
135
    my $hasText = 0;
136
137
    foreach my $cell(@$cells){
138
        $hasText = 1 if ($cell->get_text() =~ /^(.*)$txt(.*)$/);
139
    }
140
141
    ok($hasText, "Intra Notices Found text '$txt' from table");
142
143
    return $self;
144
}
145
146
sub verifyNoMessages {
147
    my ($self, $note) = @_;
148
    my $d = $self->getDriver();
149
    $self->debugTakeSessionSnapshot();
150
151
    my $dialog = $d->find_element("div.yui-b div.dialog", 'css')->get_text();
152
153
    ok($dialog =~ /^There is no record of any(.*)$/, "Intra Notices No messages sent");
154
155
    return $self;
156
}
157
158
sub openNotice {
159
    my ($self, $titleText) = @_;
160
    my $d = $self->getDriver();
161
    $self->debugTakeSessionSnapshot();
162
163
    my @titles = $d->find_elements(".notice-title", 'css');
164
165
    my $opened = 0;
166
    foreach my $title (@titles){
167
        if ($title->get_text() eq $titleText) {
168
            $title->click();
169
            $opened++;
170
        }
171
    }
172
173
    ok(($opened > 0), "Opened ". $opened ." notices '".$titleText."' successfully.");
174
175
    return $self;
176
}
177
178
sub resendMessage {
179
    my ($self, $titleText, $shouldSucceed) = @_;
180
    my $d = $self->getDriver();
181
    $self->debugTakeSessionSnapshot();
182
183
    my @resendLinks = $d->find_elements('//tr/td[a//text()[contains(.,\''.$titleText.'\')]]/following-sibling::td[2]/div/a[text()=\'Resend\']', 'xpath');
184
185
    my $resent = 0;
186
    foreach my $link (@resendLinks){
187
        $link->click();
188
        $resent++;
189
    }
190
    is(($resent > 0) ? 1:0, $shouldSucceed, "Resent ". $resent ." notices '".$titleText."' successfully.");
191
192
    return $self;
193
}
194
195
1;
(-)a/t/lib/Page/Members/Pay.pm (+106 lines)
Line 0 Link Here
1
package t::lib::Page::Members::Pay;
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Scalar::Util qw(blessed);
22
use Test::More;
23
24
use base qw(t::lib::Page::Intra t::lib::Page::Members::Toolbar t::lib::Page::Members::LeftNavigation);
25
26
use t::lib::Page::Members::ApiKeys;
27
28
use Koha::Exception::BadParameter;
29
30
=head NAME t::lib::Page::Members::Pay
31
32
=head SYNOPSIS
33
34
pay.pl PageObject providing page functionality as a service!
35
36
=cut
37
38
=head new
39
40
    my $pay = t::lib::Page::Members::Pay->new({borrowernumber => "1"});
41
42
Instantiates a WebDriver and loads the members/pay.pl.
43
@PARAM1 HASHRef of optional and MANDATORY parameters
44
MANDATORY extra parameters:
45
    borrowernumber => loads the page to display Borrower matching the given borrowernumber
46
47
@RETURNS t::lib::Page::Members::Pay, ready for user actions!
48
=cut
49
50
sub new {
51
    my ($class, $params) = @_;
52
    unless (ref($params) eq 'HASH' || (blessed($params) && $params->isa('t::lib::Page') )) {
53
        $params = {};
54
    }
55
    $params->{resource} = '/cgi-bin/koha/members/pay.pl';
56
    $params->{type}     = 'staff';
57
58
    $params->{getParams} = [];
59
    #Handle MANDATORY parameters
60
    if ($params->{borrowernumber}) {
61
        push @{$params->{getParams}}, "borrowernumber=".$params->{borrowernumber};
62
    }
63
    else {
64
        Koha::Exception::BadParameter->throw(error => __PACKAGE__."->new():> Parameter 'borrowernumber' is missing.");
65
    }
66
67
    my $self = $class->SUPER::new($params);
68
69
    return $self;
70
}
71
72
################################################################################
73
=head UI Mapping helper subroutines
74
See. Selenium documentation best practices for UI element mapping to common language descriptions.
75
=cut
76
################################################################################
77
78
sub PayAmount{
79
    my ($self) = @_;
80
    my $d = $self->getDriver();
81
    $self->debugTakeSessionSnapshot();
82
83
    my $tab = $d->find_element("input[id='paycollect'][type='submit']", 'css');
84
    $tab->click();
85
    ok($d->get_title() =~ m/Collect fine payment for/, "Intra Navigate to Paycollect (all fines)");
86
87
    $self->debugTakeSessionSnapshot();
88
89
    return t::lib::Page::Members::Paycollect->rebrandFromPageObject($self);
90
}
91
92
sub PaySelected {
93
    my ($self) = @_;
94
    my $d = $self->getDriver();
95
    $self->debugTakeSessionSnapshot();
96
97
    my $tab = $d->find_element("input[id='payselected'][type='submit']", 'css');
98
    $tab->click();
99
    ok($d->get_title() =~ m/Collect fine payment for/, "Intra Navigate to Paycollect (selected fines)");
100
101
    $self->debugTakeSessionSnapshot();
102
103
    return t::lib::Page::Members::Paycollect->rebrandFromPageObject($self);
104
}
105
106
1; #Make the compiler happy!
(-)a/t/lib/Page/Members/Paycollect.pm (+276 lines)
Line 0 Link Here
1
package t::lib::Page::Members::Paycollect;
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Scalar::Util qw(blessed);
22
use Test::More;
23
24
use base qw(t::lib::Page::Intra t::lib::Page::Members::Toolbar t::lib::Page::Members::LeftNavigation);
25
26
use t::lib::Page::Members::ApiKeys;
27
28
use Selenium::Remote::WDKeys;
29
30
use Koha::Exception::BadParameter;
31
32
=head NAME t::lib::Page::Members::Paycollect
33
34
=head SYNOPSIS
35
36
paycollect.pl PageObject providing page functionality as a service!
37
38
=cut
39
40
=head new
41
42
    my $paycollect = t::lib::Page::Members::Paycollect->new({borrowernumber => "1", selected => "1,2,3,4,5"});
43
44
Instantiates a WebDriver and loads the members/paycollect.pl.
45
@PARAM1 HASHRef of optional and MANDATORY parameters
46
MANDATORY extra parameters:
47
    borrowernumber => loads the page to display Borrower matching the given borrowernumber
48
49
@RETURNS t::lib::Page::Members::Paycollect, ready for user actions!
50
=cut
51
52
sub new {
53
    my ($class, $params) = @_;
54
    unless (ref($params) eq 'HASH' || (blessed($params) && $params->isa('t::lib::Page') )) {
55
        $params = {};
56
    }
57
    $params->{resource} = '/cgi-bin/koha/members/paycollect.pl';
58
    $params->{type}     = 'staff';
59
60
    $params->{getParams} = [];
61
    #Handle MANDATORY parameters
62
    if ($params->{borrowernumber}) {
63
        push @{$params->{getParams}}, "borrowernumber=".$params->{borrowernumber};
64
    }
65
    else {
66
        Koha::Exception::BadParameter->throw(error => __PACKAGE__."->new():> Parameter 'borrowernumber' is missing.");
67
    }
68
69
    if ($params->{selected}) {
70
        push @{$params->{getParams}}, "selected=".$params->{selected};
71
    }
72
73
    my $self = $class->SUPER::new($params);
74
75
    return $self;
76
}
77
78
################################################################################
79
=head UI Mapping helper subroutines
80
See. Selenium documentation best practices for UI element mapping to common language descriptions.
81
=cut
82
################################################################################
83
84
sub addNewCashRegister {
85
    my ($self, $cashregisternumber) = @_;
86
    my $d = $self->getDriver();
87
    $self->debugTakeSessionSnapshot();
88
89
    my $input = $d->find_element("input[id='office_new']", 'css');
90
    $input->clear();
91
    $input->send_keys($cashregisternumber);
92
    my $button = $d->find_element("button[id='new_office']", 'css');
93
    $button->click();
94
95
    my $ok = 1 if $d->find_element("button[id='office-".$cashregisternumber."']",'css');
96
    ok($ok, "Intra Added a new cash register '".$cashregisternumber."'");
97
98
    $self->debugTakeSessionSnapshot();
99
100
    return $self;
101
}
102
103
sub addNoteToSelected {
104
    my ($self, $note) = @_;
105
    my $d = $self->getDriver();
106
    $self->debugTakeSessionSnapshot();
107
108
    my $input = $d->find_element("textarea[id='selected_accts_notes']", 'css');
109
    $input->clear();
110
    $input->send_keys($note);
111
112
    $self->debugTakeSessionSnapshot();
113
114
    return $self;
115
}
116
117
sub confirmPayment {
118
    my ($self) = @_;
119
    my $d = $self->getDriver();
120
    $self->debugTakeSessionSnapshot();
121
122
    my $confirm = $d->find_element("input[name='submitbutton'][type='submit']",'css');
123
124
    $confirm->click();
125
126
    ok(1, "Intra Confirmed payment");
127
    $self->debugTakeSessionSnapshot();
128
129
    return t::lib::Page::Members::Paycollect->rebrandFromPageObject($self);
130
}
131
132
sub openAddNewCashRegister {
133
    my ($self) = @_;
134
    my $d = $self->getDriver();
135
    $self->debugTakeSessionSnapshot();
136
137
    my $link = $d->find_element("span[id='add_new_office'] a", 'css');
138
    $link->click();
139
    ok($d->find_element("input[id='office_new']",'css'), "Intra Opened input for adding a new cash register");
140
141
    $self->debugTakeSessionSnapshot();
142
143
    return $self;
144
}
145
146
sub paymentLoadingScreen {
147
    my ($self, $cashregisternumber) = @_;
148
    my $d = $self->getDriver();
149
    $self->debugTakeSessionSnapshot();
150
151
    my $ok = 1 if $d->find_element("button[id='recheck']",'css');
152
153
    ok($ok, "Intra Payment loading screen open");
154
155
    return $self;
156
}
157
158
sub selectCashRegister {
159
    my ($self, $cashregisternumber) = @_;
160
    my $d = $self->getDriver();
161
    $self->debugTakeSessionSnapshot();
162
163
    my $cashregister = $d->find_element("button[id='office-".$cashregisternumber."']",'css');
164
165
    $cashregister->click();
166
167
    my $ok = 1 if $d->find_element("button[id='office-".$cashregisternumber."'][class='office-button selected']",'css');
168
    ok($ok, "Intra Selected cash register '".$cashregisternumber."'");
169
    $self->debugTakeSessionSnapshot();
170
171
    return $self;
172
}
173
174
sub sendPaymentToPOS {
175
    my ($self) = @_;
176
    my $d = $self->getDriver();
177
    $self->debugTakeSessionSnapshot();
178
179
    my $confirm = $d->find_element("input[name='submitbutton'][type='submit']",'css');
180
181
    # $confirm->click() is broken. It doesn't move on until AJAX at next page is completed. Need to use
182
    # alternative method. Click submit with JavaScript and poll until loading screen is open.
183
    my $script = q{
184
        $("input[name='submitbutton'][type='submit']").click();
185
    };
186
    $d->execute_script($script);
187
188
    my $func = undef; # we only need to poll for success
189
    my $success = sub {
190
        eval {
191
            my $el = $d->find_element("button[id='recheck']",'css');
192
        };
193
        if ($@) {
194
            return 0;
195
        }
196
        return 1;
197
    };
198
199
    $self->poll($func, $success, 50, 100); # poll for max 5 seconds
200
201
    ok(1, "Intra Sent payment to cash register");
202
    $self->debugTakeSessionSnapshot();
203
204
    return t::lib::Page::Members::Paycollect->rebrandFromPageObject($self);
205
}
206
207
sub setAmount {
208
    my ($self, $amount) = @_;
209
    my $d = $self->getDriver();
210
    $self->debugTakeSessionSnapshot();
211
212
    my $input = $d->find_element("input[name='paid']", 'css');
213
    # Clear and send_keys did not work. Set values by JS
214
    my $script = qq(('#paid').val('$amount'););
215
    $d->execute_script('$'.$script);
216
217
    is($input->get_value(), $amount, "Intra Set payment amount to ".$amount);
218
    $self->debugTakeSessionSnapshot();
219
220
    return $self;
221
}
222
223
sub waitUntilPaymentIsAcceptedAtPOS {
224
    my ($self) = @_;
225
226
    return waitUntilPaymentIsCompletedAtPOS($self, "paid");
227
}
228
sub waitUntilPaymentIsCancelledAtPOS {
229
    my ($self) = @_;
230
231
    return waitUntilPaymentIsCompletedAtPOS($self, "cancelled");
232
}
233
sub waitUntilPaymentIsCompletedAtPOS {
234
    my ($self, $status) = @_;
235
    my $d = $self->getDriver();
236
    $self->debugTakeSessionSnapshot();
237
238
    my $recheck = $d->find_element("button[id='recheck']",'css');
239
240
    my $func = undef; # we only need to poll for success
241
    my $success = sub {
242
        eval {
243
            my $el = $d->find_element("span#status span.".$status."[style*='inline-block']",'css');
244
        };
245
        if ($@) {
246
            return 0;
247
        }
248
        return 1;
249
    };
250
251
    $self->poll($func, $success, 50, 100); # poll for max 5 seconds
252
253
    ok(1, "Payment is completed");
254
    $self->debugTakeSessionSnapshot();
255
256
    # Poll until "recheck" button is not found. This means we have been
257
    # redirected to Boraccount
258
    $func = undef; # we only need to poll for success
259
    $success = sub {
260
        eval {
261
            my $el = $d->find_element("button[id='recheck']",'css');
262
        };
263
        if ($@) {
264
            return 1;
265
        }
266
        return 0;
267
    };
268
269
    $self->poll($func, $success, 50, 100); # poll for max 5 seconds
270
271
    $self->debugTakeSessionSnapshot();
272
273
    return t::lib::Page::Members::Boraccount->rebrandFromPageObject($self);
274
}
275
276
1; #Make the compiler happy!
(-)a/t/lib/Page/Members/Toolbar.pm (+154 lines)
Line 0 Link Here
1
package t::lib::Page::Members::Toolbar;
2
3
# Copyright 2015 KohaSuomi!
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Test::More;
22
23
use Koha::Exception::BadParameter;
24
25
=head NAME t::lib::Page::Members::Toolbar
26
27
=head SYNOPSIS
28
29
PageObject Accessory representing a shared Template between PageObjects.
30
This encapsulates specific page-related functionality.
31
32
In this case this encapsulates the members-module toolbar's services and provides
33
a reusable class from all member-module PageObjects.
34
35
=cut
36
37
################################################################################
38
=head UI Mapping helper subroutines
39
See. Selenium documentation best practices for UI element mapping to common language descriptions.
40
=cut
41
################################################################################
42
43
=head _getToolbarActionElements
44
Shares the same toolbar with moremember.pl
45
@RETURNS HASHRef of Selenium::Driver::Webelements matching all the clickable elements
46
                 in the actions toolbar over the Borrower information.
47
=cut
48
49
sub _getToolbarActionElements {
50
    my ($self) = @_;
51
    my $d = $self->getDriver();
52
53
    my $editA = $d->find_element("#editpatron", 'css');
54
    my $changePasswordA = $d->find_element("#changepassword", 'css');
55
    my $duplicateA = $d->find_element("#duplicate", 'css');
56
    my $printButton = $d->find_element("#duplicate + div > button", 'css');
57
    my $searchToHoldA = $d->find_element("#searchtohold", 'css');
58
    my $addNewMessage = $d->find_element("#addnewmessageLabel", 'css');
59
    my $moreButton = $d->find_element("//button[contains(.,'More')]", 'xpath');
60
61
    my $e = {};
62
    $e->{edit} = $editA if $editA;
63
    $e->{changePassword} = $changePasswordA if $changePasswordA;
64
    $e->{duplicate} = $duplicateA if $duplicateA;
65
    $e->{print} = $printButton if $printButton;
66
    $e->{searchToHold} = $searchToHoldA if $searchToHoldA;
67
    $e->{addNewMessage} = $addNewMessage if $addNewMessage;
68
    $e->{more} = $moreButton if $moreButton;
69
    return $e;
70
}
71
72
=head _getMoreDropdownElements
73
Clicks the dropdown open if it isnt yet.
74
@RETURNS HASHRef of all the dropdown elements under the More button in the toolbar
75
                 over Borrower information.
76
=cut
77
78
sub _getMoreDropdownElements {
79
    my ($self) = @_;
80
    my $d = $self->getDriver();
81
82
    my $toolbarElements = $self->_getToolbarActionElements();
83
    my $moreButton = $toolbarElements->{more};
84
    my $deleteA;
85
    eval {
86
        $deleteA = $d->find_child_element($moreButton, "#deletepatron", 'css');
87
    };
88
    unless ($deleteA && $deleteA->is_visible()) {
89
        $moreButton->click();
90
        $self->debugTakeSessionSnapshot();
91
    }
92
93
    my $renewPatronA      = $d->find_element("#renewpatron", 'css');
94
    my $setPermissionsA   = $d->find_element("#patronflags", 'css');
95
    my $manageApiKeysA    = $d->find_element("#apikeys", 'css');
96
       $deleteA           = $d->find_element("#deletepatron", 'css');
97
    $self->debugTakeSessionSnapshot();
98
    my $updateChildToAdultPatronA = $d->find_element("#updatechild", 'css');
99
    my $exportCheckinBarcodesA = $d->find_element("#exportcheckins", 'css');
100
101
    my $e = {};
102
    $e->{renewPatron}     = $renewPatronA if $renewPatronA;
103
    $e->{setPermissions}  = $setPermissionsA if $setPermissionsA;
104
    $e->{manageApiKeys}   = $manageApiKeysA if $manageApiKeysA;
105
    $e->{delete}          = $deleteA if $deleteA;
106
    $e->{updateChildToAdultPatron} = $updateChildToAdultPatronA if $updateChildToAdultPatronA;
107
    $e->{exportCheckinBarcodes} = $exportCheckinBarcodesA if $exportCheckinBarcodesA;
108
    return $e;
109
}
110
111
112
################################################################################
113
=head PageObject Services
114
115
=cut
116
################################################################################
117
118
sub navigateManageApiKeys {
119
    my ($self) = @_;
120
    my $d = $self->getDriver();
121
    $self->debugTakeSessionSnapshot();
122
123
    my $elements = $self->_getMoreDropdownElements();
124
    $elements->{manageApiKeys}->click();
125
    ok($d->get_title() =~ m/API Keys/, "Intra Navigate to Manage API Keys");
126
127
    $self->debugTakeSessionSnapshot();
128
129
    return t::lib::Page::Members::ApiKeys->rebrandFromPageObject($self);
130
}
131
sub navigateEditPatron {
132
    my ($self) = @_;
133
    my $d = $self->getDriver();
134
    $self->debugTakeSessionSnapshot();
135
136
    my $elements = $self->_getToolbarActionElements();
137
138
    my $func = sub {
139
        $elements->{edit}->click();
140
    };
141
    my $success = sub {
142
        return $self->getDriver()->get_title() =~ m/Modify(.*)patron/;
143
    };
144
145
    $self->poll($func, $success, 20, 50);
146
147
    ok($d->get_title() =~ m/Modify(.*)patron/, "Intra Navigate to Modify patron");
148
    $self->debugTakeSessionSnapshot();
149
150
    return t::lib::Page::Members::Memberentry->rebrandFromPageObject($self);
151
}
152
153
154
1; #Make the compiler happy!
(-)a/t/lib/Page/Opac.pm (+238 lines)
Line 0 Link Here
1
package t::lib::Page::Opac;
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Test::More;
22
23
use C4::Context;
24
25
use t::lib::WebDriverFactory;
26
27
use Koha::Exception::BadParameter;
28
use Koha::Exception::SystemCall;
29
30
use base qw(t::lib::Page);
31
32
=head NAME t::lib::Page::Opac
33
34
=head SYNOPSIS
35
36
PageObject-pattern parent class for OPAC-pages. Extend this to implement specific pages shown to our users.
37
38
=cut
39
40
################################################################################
41
=head UI Mapping helper subroutines
42
See. Selenium documentation best practices for UI element mapping to common language descriptions.
43
=cut
44
################################################################################
45
46
=head _getHeaderRegionActionElements
47
48
Returns each element providing some kind of an action from the topmost header bar in OPAC.
49
All elements are not always present on each page, so test if the return set contains your
50
desired element.
51
@PARAM1 Selenium::Remote::Driver
52
@RETURNS HASHRef of the found elements:
53
    { cart             => $cartA,
54
      lists            => $listsA,
55
      loggedinusername => $loggedinusernameA,
56
      searchHistory    => $searchHistoryA,
57
      deleteSearchHistory => $deleteSearchHistoryA,
58
      logout           => $logoutA,
59
      login            => $loginA,
60
    }
61
=cut
62
63
sub _getHeaderRegionActionElements {
64
    my ($self) = @_;
65
    my $d = $self->getDriver();
66
67
    my ($cartA, $listsA, $loggedinusernameA, $searchHistoryA, $deleteSearchHistoryA, $logoutA, $loginA);
68
    #Always visible elements
69
    $cartA = $d->find_element("#header-region a#cartmenulink");
70
    $listsA = $d->find_element("#header-region a#listsmenu");
71
    #Occasionally visible elements
72
    eval {
73
        $loggedinusernameA = $d->find_element("#header-region a[href*='opac-user.pl']");
74
    };
75
    eval {
76
        $searchHistoryA = $d->find_element("#header-region a[href*='opac-search-history.pl']");
77
    };
78
    eval {
79
        $deleteSearchHistoryA = $d->find_element("#header-region a[href*='opac-search-history.pl'] + a");
80
    };
81
    eval {
82
        $logoutA = $d->find_element("#header-region #logout");
83
    };
84
    eval {
85
        $loginA = $d->find_element("#header-region #members a.loginModal-trigger");
86
    };
87
88
    my $e = {};
89
    $e->{cart} = $cartA if $cartA;
90
    $e->{lists} = $listsA if $listsA;
91
    $e->{loggedinusername} = $loggedinusernameA if $loggedinusernameA;
92
    $e->{searchHistory} = $searchHistoryA if $searchHistoryA;
93
    $e->{deleteSearchHistory} = $deleteSearchHistoryA if $deleteSearchHistoryA;
94
    $e->{logout} = $logoutA if $logoutA;
95
    $e->{login} = $loginA if $loginA;
96
    return ($e);
97
}
98
99
sub _getMoresearchesElements {
100
    my ($self) = @_;
101
    my $d = $self->getDriver();
102
103
    my $advancedSearchA = $d->find_element("#moresearches a[href*='opac-search.pl']");
104
    my $authoritySearchA = $d->find_element("#moresearches a[href*='opac-authorities-home.pl']");
105
    my $tagCloudA = $d->find_element("#moresearches a[href*='opac-tags.pl']");
106
    return ($advancedSearchA, $authoritySearchA, $tagCloudA);
107
}
108
109
sub _getBreadcrumbLinks {
110
    my ($self) = @_;
111
    my $d = $self->getDriver();
112
113
    my $breadcrumbLinks = $d->find_elements("ul.breadcrumb a");
114
    return ($breadcrumbLinks);
115
}
116
117
118
119
################################################################################
120
=head PageObject Services
121
122
=cut
123
################################################################################
124
125
=head isPasswordLoginAvailable
126
127
    $page->isPasswordLoginAvailable();
128
129
@RETURN t::lib::Page-object
130
@CROAK if password login is unavailable.
131
=cut
132
133
sub isPasswordLoginAvailable {
134
    my $self = shift;
135
    my $d = $self->getDriver();
136
    $self->debugTakeSessionSnapshot();
137
138
    $self->_getPasswordLoginElements();
139
    ok(1, "PasswordLogin available");
140
    return $self;
141
}
142
143
sub doPasswordLogin {
144
    my ($self, $username, $password) = @_;
145
    my $d = $self->getDriver();
146
    $self->debugTakeSessionSnapshot();
147
148
    my ($submitButton, $useridInput, $passwordInput) = $self->_getPasswordLoginElements();
149
    $useridInput->send_keys($username);
150
    $passwordInput->send_keys($password);
151
    $submitButton->click();
152
    $self->debugTakeSessionSnapshot();
153
154
    my $cookies = $d->get_all_cookies();
155
    my @cgisessid = grep {$_->{name} eq 'CGISESSID'} @$cookies;
156
157
    my $loggedinusernameSpan = $d->find_element('span.loggedinusername');
158
    ok(($cgisessid[0]), "PasswordLogin succeeded"); #We have the element && Cookie CGISESSID defined!
159
160
    return $self; #After a succesfull password login, we are directed to the same page we tried to access.
161
}
162
163
sub failPasswordLogin {
164
    my ($self, $username, $password) = @_;
165
    my $d = $self->getDriver();
166
    $self->debugTakeSessionSnapshot();
167
168
    my ($submitButton, $useridInput, $passwordInput) = $self->_getPasswordLoginElements();
169
    $useridInput->send_keys($username);
170
    $passwordInput->send_keys($password);
171
    $submitButton->click();
172
    $self->debugTakeSessionSnapshot();
173
174
    ok($d->get_title() =~ /Log in to your account/ #Still in the login page
175
       , "Opac PasswordLogin failed");
176
177
    return $self; #After a successful password login, we are directed to the same page we tried to access.
178
}
179
180
sub doPasswordLogout {
181
    my ($self, $username, $password) = @_;
182
    my $d = $self->getDriver();
183
    $self->debugTakeSessionSnapshot();
184
185
    #Logout
186
    my $headerElements = $self->_getHeaderRegionActionElements();
187
    my $logoutA = $headerElements->{logout};
188
    $logoutA->click();
189
    $self->debugTakeSessionSnapshot();
190
191
    $headerElements = $self->_getHeaderRegionActionElements(); #Take the changed header elements
192
    ok(($headerElements->{login}->get_text() =~ /Log in/ ||
193
        $d->get_title() =~ /Log in to your account/), "Opac Header PasswordLogout succeeded");
194
195
    return t::lib::Page::Opac::OpacMain->rebrandFromPageObject($self);
196
}
197
198
sub navigateSearchHistory {
199
    my ($self) = @_;
200
    my $d = $self->getDriver();
201
    $self->debugTakeSessionSnapshot();
202
203
    my $headerElements = $self->_getHeaderRegionActionElements();
204
    my $searchHistoryA = $headerElements->{searchHistory};
205
    $searchHistoryA->click();
206
    $self->debugTakeSessionSnapshot();
207
208
    ok(($d->get_title() =~ /Your search history/), "Opac Navigation to search history.");
209
    return t::lib::Page::Opac::OpacSearchHistory->rebrandFromPageObject($self);
210
}
211
212
sub navigateAdvancedSearch {
213
    my ($self) = @_;
214
    my $d = $self->getDriver();
215
    $self->debugTakeSessionSnapshot();
216
217
    my ($advancedSearchA, $authoritySearchA, $tagCloudA) = $self->_getMoresearchesElements();
218
    $advancedSearchA->click();
219
220
    $self->debugTakeSessionSnapshot();
221
    ok(($d->get_title() =~ /Advanced search/), "Opac Navigating to advanced search.");
222
    return t::lib::Page::Opac::OpacSearch->rebrandFromPageObject($self);
223
}
224
225
sub navigateHome {
226
    my ($self) = @_;
227
    my $d = $self->getDriver();
228
    $self->debugTakeSessionSnapshot();
229
230
    my $breadcrumbLinks = $self->_getBreadcrumbLinks();
231
    $breadcrumbLinks->[0]->click();
232
233
    $self->debugTakeSessionSnapshot();
234
    ok(($d->get_current_url() =~ /opac-main\.pl/), "Opac Navigating to OPAC home.");
235
    return t::lib::Page::Opac::OpacMain->rebrandFromPageObject($self);
236
}
237
238
1; #Make the compiler happy!
(-)a/t/lib/Page/Opac/LeftNavigation.pm (+167 lines)
Line 0 Link Here
1
package t::lib::Page::Opac::LeftNavigation;
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Scalar::Util qw(blessed);
22
use Test::More;
23
24
use t::lib::Page::Opac::OpacApiKeys;
25
use t::lib::Page::Opac::OpacMessaging;
26
27
=head NAME t::lib::Page::Opac::LeftNavigation
28
29
=head SYNOPSIS
30
31
Provides the services of the Opac left navigation column/frame for the implementing PageObject
32
33
=cut
34
35
################################################################################
36
=head UI Mapping helper subroutines
37
See. Selenium documentation best practices for UI element mapping to common language descriptions.
38
=cut
39
################################################################################
40
41
=head _getLeftNavigationActionElements
42
@RETURNS HASHRef of Selenium::Driver::Webelements matching all the clickable elements
43
                 in the left navigation frame/column at all Opac pages requiring login.
44
=cut
45
46
sub _getLeftNavigationActionElements {
47
    my ($self) = @_;
48
    my $d = $self->getDriver();
49
50
    my $e = {};
51
    eval {
52
        $e->{yourSummary} = $d->find_element("a[href*='opac-user.pl']", 'css');
53
    };
54
    eval {
55
        $e->{yourFines}   = $d->find_element("a[href*='opac-account.pl']", 'css');
56
    };
57
    eval {
58
        $e->{yourPersonalDetails} = $d->find_element("a[href*='opac-memberentry.pl']", 'css');
59
    };
60
    eval {
61
        $e->{yourTags}    = $d->find_element("a[href*='opac-tags.pl']", 'css');
62
    };
63
    eval {
64
        $e->{changeYourPassword} = $d->find_element("a[href*='opac-passwd.pl']", 'css');
65
    };
66
    eval {
67
        $e->{yourSearchHistory} = $d->find_element("a[href*='opac-search-history.pl']", 'css');
68
    };
69
    eval {
70
        $e->{yourReadingHistory} = $d->find_element("a[href*='opac-readingrecord.pl']", 'css');
71
    };
72
    eval {
73
        $e->{yourPurchaseSuggestions} = $d->find_element("a[href*='opac-suggestions.pl']", 'css');
74
    };
75
    eval {
76
        $e->{yourMessaging} = $d->find_element("a[href*='opac-messaging.pl']", 'css');
77
    };
78
    eval {
79
        $e->{yourLists} = $d->find_element("a[href*='opac-shelves.pl']", 'css');
80
    };
81
    eval {
82
        $e->{yourAPIKeys} = $d->find_element("a[href*='opac-apikeys.pl']", 'css');
83
    };
84
    return $e;
85
}
86
87
88
89
################################################################################
90
=head PageObject Services
91
92
=cut
93
################################################################################
94
95
sub navigateYourAPIKeys {
96
    my ($self) = @_;
97
    my $d = $self->getDriver();
98
    $self->debugTakeSessionSnapshot();
99
100
    my $elements = $self->_getLeftNavigationActionElements();
101
    $elements->{yourAPIKeys}->click();
102
    $self->debugTakeSessionSnapshot();
103
104
    my $breadcrumbs = $self->_getBreadcrumbLinks();
105
106
    ok(ref($breadcrumbs) eq 'ARRAY' &&
107
       $breadcrumbs->[scalar(@$breadcrumbs)-1]->get_text() =~ m/API keys/i,
108
       "Opac Navigate to Your API Keys");
109
110
    return t::lib::Page::Opac::OpacApiKeys->rebrandFromPageObject($self);
111
}
112
113
sub navigateYourMessaging {
114
    my ($self) = @_;
115
    my $d = $self->getDriver();
116
    $self->debugTakeSessionSnapshot();
117
118
    my $elements = $self->_getLeftNavigationActionElements();
119
    $elements->{yourMessaging}->click();
120
    $self->debugTakeSessionSnapshot();
121
122
    my $breadcrumbs = $self->_getBreadcrumbLinks();
123
124
    ok(ref($breadcrumbs) eq 'ARRAY' &&
125
       $breadcrumbs->[scalar(@$breadcrumbs)-1]->get_text() =~ m/Your messaging/i,
126
       "Opac Navigate to Your messaging");
127
128
    return t::lib::Page::Opac::OpacMessaging->rebrandFromPageObject($self);
129
}
130
131
sub navigateYourPersonalDetails {
132
    my ($self) = @_;
133
    my $d = $self->getDriver();
134
    $self->debugTakeSessionSnapshot();
135
136
    my $elements = $self->_getLeftNavigationActionElements();
137
    $elements->{yourPersonalDetails}->click();
138
    $self->debugTakeSessionSnapshot();
139
140
    my $breadcrumbs = $self->_getBreadcrumbLinks();
141
142
    ok(ref($breadcrumbs) eq 'ARRAY' &&
143
       $breadcrumbs->[scalar(@$breadcrumbs)-1]->get_text() =~ m/Your personal details/i,
144
       "Opac Navigate to Your personal details");
145
146
    return t::lib::Page::Opac::OpacMemberentry->rebrandFromPageObject($self);
147
}
148
149
sub navigateYourFines {
150
    my ($self) = @_;
151
    my $d = $self->getDriver();
152
    $self->debugTakeSessionSnapshot();
153
154
    my $elements = $self->_getLeftNavigationActionElements();
155
    $elements->{yourFines}->click();
156
    $self->debugTakeSessionSnapshot();
157
158
    my $breadcrumbs = $self->_getBreadcrumbLinks();
159
160
    ok(ref($breadcrumbs) eq 'ARRAY' &&
161
       $breadcrumbs->[scalar(@$breadcrumbs)-1]->get_text() =~ m/Your fines and charges/i,
162
       "Opac Navigate to Your fines");
163
164
    return t::lib::Page::Opac::OpacAccount->rebrandFromPageObject($self);
165
}
166
167
1; #Make the compiler happy!
(-)a/t/lib/Page/Opac/OpacAccount.pm (+142 lines)
Line 0 Link Here
1
package t::lib::Page::Opac::OpacAccount;
2
3
# Copyright 2016 KohaSuomi
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public Lice strongnse
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Scalar::Util qw(blessed);
22
use Test::More;
23
24
use t::lib::Page::Opac::OpacAccount;
25
use t::lib::Page::Opac::OpacPaycollect;
26
27
use base qw(t::lib::Page::Opac t::lib::Page::Opac::LeftNavigation);
28
29
use Koha::Exception::BadParameter;
30
31
=head NAME t::lib::Page::Opac::OpacAccount
32
33
=head SYNOPSIS
34
35
PageObject providing page functionality as a service!
36
37
=cut
38
39
=head new
40
41
    my $opacaccount = t::lib::Page::Opac::OpacAccount->new();
42
43
Instantiates a WebDriver and loads the opac/opac-account.pl.
44
@PARAM1 HASHRef of optional and MANDATORY parameters
45
MANDATORY extra parameters:
46
    none atm.
47
48
@RETURNS t::lib::Page::Opac::OpacAccount, ready for user actions!
49
=cut
50
51
sub new {
52
    my ($class, $params) = @_;
53
    unless (ref($params) eq 'HASH' || (blessed($params) && $params->isa('t::lib::Page') )) {
54
        $params = {};
55
    }
56
    $params->{resource} = '/cgi-bin/koha/opac-account.pl';
57
    $params->{type}     = 'opac';
58
59
    my $self = $class->SUPER::new($params);
60
61
    return $self;
62
}
63
64
################################################################################
65
=head UI Mapping helper subroutines
66
See. Selenium documentation best practices for UI element mapping to common language descriptions.
67
=cut
68
################################################################################
69
70
sub findFine {
71
    my ($self, $note) = @_;
72
    my $d = $self->getDriver();
73
    $self->debugTakeSessionSnapshot();
74
75
    my $payment_note = $d->find_element("//td[contains(.,\"".$note."\")]", "xpath");
76
77
    ok(1, "Opac Found payment with description ".$note);
78
79
    return $self;
80
}
81
82
sub isFinePaid {
83
    my ($self, $note, $noteColumnIndex, $amountOutstandingColumnIndex) = @_;
84
85
    return isFineAmountOutstanding($self, $note, "0.00", $noteColumnIndex, $amountOutstandingColumnIndex);
86
}
87
88
sub isFineAmount {
89
    my ($self, $note, $amount, $noteColumnIndex, $amountColumnIndex) = @_;
90
    my $d = $self->getDriver();
91
    $self->debugTakeSessionSnapshot();
92
93
    $noteColumnIndex = 2 if not defined $noteColumnIndex;
94
    $amountColumnIndex = 3 if not defined $amountColumnIndex;
95
96
    my $fine = $d->find_element("//tr[(td[".$noteColumnIndex."][contains(.,\"".$note."\")]) and (td[".$amountColumnIndex."][text()=\"".$amount."\"])]", "xpath");
97
98
    ok(1, "Opac Found payment with note ".$note." and amount ".$amount);
99
100
    return $self;
101
}
102
103
sub isFineAmountOutstanding {
104
    my ($self, $note, $amountOutstanding, $noteColumnIndex, $amountOutstandingColumnIndex) = @_;
105
    my $d = $self->getDriver();
106
    $self->debugTakeSessionSnapshot();
107
108
    $noteColumnIndex = 2 if not defined $noteColumnIndex;
109
    $amountOutstandingColumnIndex = 4 if not defined $amountOutstandingColumnIndex;
110
111
    my $fine = $d->find_element("//tr[(td[".$noteColumnIndex."][contains(.,\"".$note."\")]) and (td[".$amountOutstandingColumnIndex."][text()=\"".$amountOutstanding."\"])]", "xpath");
112
113
    ok(1, "Opac Found payment with note ".$note." and amountoutstanding ".$amountOutstanding);
114
115
    return $self;
116
}
117
118
sub isEverythingPaid {
119
    my ($self) = @_;
120
    my $d = $self->getDriver();
121
    $self->debugTakeSessionSnapshot();
122
123
    my $transaction_columns = $d->find_element("//td[contains(\@class, 'sum') and text() = '0.00']", "xpath");
124
125
    ok(1, "Opac Found total due 0.00, no outstanding fines");
126
127
    return $self;
128
}
129
130
sub PayFines {
131
    my ($self) = @_;
132
    my $d = $self->getDriver();
133
    $self->debugTakeSessionSnapshot();
134
135
    my $payButton = $d->find_element("button.pay-fines", "css");
136
137
    $payButton->click();
138
139
    return t::lib::Page::Opac::OpacPaycollect->rebrandFromPageObject($self);;
140
}
141
142
1;
(-)a/t/lib/Page/Opac/OpacApiKeys.pm (+170 lines)
Line 0 Link Here
1
package t::lib::Page::Opac::OpacApiKeys;
2
3
# Copyright 2015 KohaSuomi!
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Scalar::Util qw(blessed);
22
use Test::More;
23
24
use base qw(t::lib::Page::Opac t::lib::Page::Opac::LeftNavigation);
25
26
use Koha::Exception::BadParameter;
27
use Koha::Exception::UnknownObject;
28
29
=head NAME t::lib::Page::Members::ApiKeys
30
31
=head SYNOPSIS
32
33
apikeys.pl PageObject providing page functionality as a service!
34
35
=cut
36
37
sub new {
38
    Koha::Exception::FeatureUnavailable->throw(error => __PACKAGE__."->new():> You must login first to navigate to this page!");
39
}
40
41
################################################################################
42
=head UI Mapping helper subroutines
43
See. Selenium documentation best practices for UI element mapping to common language descriptions.
44
=cut
45
################################################################################
46
47
=head _getActionsAndTableElements
48
@RETURNS List of
49
         HASHRef of Selenium::Driver::Webelement-objects matching the generic
50
                 actions on this page, eg. 'generateNewKey'.
51
         HASHRef of Selenium::Driver::Webelement-objects keyed with the apiKey hash/text.
52
                 These are all the apiKey table rows present, and have the
53
                 elements prefetched for easy access.
54
55
=cut
56
57
sub _getActionsAndTableElements {
58
    my ($self) = @_;
59
    my $d = $self->getDriver();
60
61
    my $generateNewKeySubmit = $d->find_element("#generatenewkey", 'css');
62
63
    my $a = {}; #Collect action elements here
64
    $a->{generateNewKey} = $generateNewKeySubmit; #Bind the global action here for easy reference.
65
66
    my $apiKeyRows;
67
    eval { #We might not have ApiKeys yet.
68
        $apiKeyRows = $d->find_elements("#apikeystable tr", 'css');
69
        shift @$apiKeyRows; #Remove the table header row
70
    };
71
    my %apiKeys;
72
    for(my $i=0 ; $i<scalar(@$apiKeyRows) ; $i++) {
73
        #Iterate every apiKey in the apiKeys table and prefetch the interesting data as text and available action elements.
74
        my $row = $apiKeyRows->[$i];
75
        $row->{'nth-of-type'} = $i+1; #starts from 1
76
        $row->{key} = $d->find_child_element($row, "td.apikeykey", 'css')->get_text();
77
        $row->{active} = $d->find_child_element($row, "td.apikeyactive", 'css')->get_text();
78
        $row->{lastTransaction} = $d->find_child_element($row, "td.apikeylastransaction", 'css')->get_text();
79
        $row->{delete} = $d->find_child_element($row, "input.apikeydelete", 'css');
80
        eval {
81
            $row->{revoke} = $d->find_child_element($row, "input.apikeyrevoke", 'css');
82
        };
83
        eval {
84
            $row->{activate} = $d->find_child_element($row, "input.apikeyactivate", 'css');
85
        };
86
        $apiKeys{$row->{key}} = $row;
87
    }
88
89
    return ($a, \%apiKeys);
90
}
91
92
93
94
################################################################################
95
=head PageObject Services
96
97
=cut
98
################################################################################
99
100
sub generateNewApiKey {
101
    my ($self) = @_;
102
    my $d = $self->getDriver();
103
    $self->debugTakeSessionSnapshot();
104
105
    my ($actionElements, $apiKeyRows) = $self->_getActionsAndTableElements();
106
    my $apiKeyRowsCountPre = (ref $apiKeyRows eq 'HASH') ? scalar(keys(%$apiKeyRows)) : 0;
107
    $actionElements->{generateNewKey}->click();
108
    $self->debugTakeSessionSnapshot();
109
110
    ($actionElements, $apiKeyRows) = $self->_getActionsAndTableElements();
111
    my $apiKeyRowsCountPost = (ref $apiKeyRows eq 'HASH') ? scalar(keys(%$apiKeyRows)) : 0;
112
    is($apiKeyRowsCountPre+1, $apiKeyRowsCountPost, "ApiKey generated");
113
    return $self;
114
}
115
116
sub revokeApiKey {
117
    my ($self, $apiKey) = @_;
118
    my $d = $self->getDriver();
119
    $self->debugTakeSessionSnapshot();
120
121
    my ($actionElements, $apiKeyRows) = $self->_getActionsAndTableElements();
122
    my $apiKeyRow = $apiKeyRows->{$apiKey};
123
    Koha::Exception::UnknownObject->throw(error => __PACKAGE__."revokeApiKey():> No matching apiKey '$apiKey' found.") unless $apiKeyRow;
124
    $apiKeyRow->{revoke}->click();
125
    $self->debugTakeSessionSnapshot();
126
127
    ($actionElements, $apiKeyRows) = $self->_getActionsAndTableElements();
128
    $apiKeyRow = $apiKeyRows->{$apiKey};
129
    Koha::Exception::UnknownObject->throw(error => __PACKAGE__."revokeApiKey():> No matching apiKey '$apiKey' found after revoking it.") unless $apiKeyRow;
130
    is($apiKeyRow->{active}, 'No', "ApiKey revoked");
131
    return $self;
132
}
133
134
sub activateApiKey {
135
    my ($self, $apiKey) = @_;
136
    my $d = $self->getDriver();
137
    $self->debugTakeSessionSnapshot();
138
139
    my ($actionElements, $apiKeyRows) = $self->_getActionsAndTableElements();
140
    my $apiKeyRow = $apiKeyRows->{$apiKey};
141
    Koha::Exception::UnknownObject->throw(error => __PACKAGE__."revokeApiKey():> No matching apiKey '$apiKey' found.") unless $apiKeyRow;
142
    $apiKeyRow->{activate}->click();
143
    $self->debugTakeSessionSnapshot();
144
145
    ($actionElements, $apiKeyRows) = $self->_getActionsAndTableElements();
146
    $apiKeyRow = $apiKeyRows->{$apiKey};
147
    Koha::Exception::UnknownObject->throw(error => __PACKAGE__."revokeApiKey():> No matching apiKey '$apiKey' found after activating it.") unless $apiKeyRow;
148
    is($apiKeyRow->{active}, 'Yes', "ApiKey activated");
149
    return $self;
150
}
151
152
sub deleteApiKey {
153
    my ($self, $apiKey) = @_;
154
    my $d = $self->getDriver();
155
    $self->debugTakeSessionSnapshot();
156
157
    my ($actionElements, $apiKeyRows) = $self->_getActionsAndTableElements();
158
    my $apiKeyRowsCountPre = (ref $apiKeyRows eq 'HASH') ? scalar(keys(%$apiKeyRows)) : 0;
159
    my $apiKeyRow = $apiKeyRows->{$apiKey};
160
    Koha::Exception::UnknownObject->throw(error => __PACKAGE__."revokeApiKey():> No matching apiKey '$apiKey' found.") unless $apiKeyRow;
161
    $apiKeyRow->{delete}->click();
162
    $self->debugTakeSessionSnapshot();
163
164
    ($actionElements, $apiKeyRows) = $self->_getActionsAndTableElements();
165
    my $apiKeyRowsCountPost = (ref $apiKeyRows eq 'HASH') ? scalar(keys(%$apiKeyRows)) : 0;
166
    is($apiKeyRowsCountPre-1, $apiKeyRowsCountPost, "ApiKey deleted");
167
    return $self;
168
}
169
170
1; #Make the compiler happy!
(-)a/t/lib/Page/Opac/OpacMain.pm (+125 lines)
Line 0 Link Here
1
package t::lib::Page::Opac::OpacMain;
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Scalar::Util qw(blessed);
22
use Test::More;
23
24
use t::lib::Page::Opac::OpacUser;
25
26
use base qw(t::lib::Page::Opac);
27
28
use Koha::Exception::BadParameter;
29
30
=head NAME t::lib::Page::Opac::OpacMain
31
32
=head SYNOPSIS
33
34
PageObject providing page functionality as a service!
35
36
=cut
37
38
=head new
39
40
    my $opacmain = t::lib::Page::Opac::OpacMain->new();
41
42
Instantiates a WebDriver and loads the opac/opac-main.pl.
43
@PARAM1 HASHRef of optional and MANDATORY parameters
44
MANDATORY extra parameters:
45
    none atm.
46
47
@RETURNS t::lib::Page::Opac::OpacMain, ready for user actions!
48
=cut
49
50
sub new {
51
    my ($class, $params) = @_;
52
    unless (ref($params) eq 'HASH' || (blessed($params) && $params->isa('t::lib::Page') )) {
53
        $params = {};
54
    }
55
    $params->{resource} = '/cgi-bin/koha/opac-main.pl';
56
    $params->{type}     = 'opac';
57
58
    my $self = $class->SUPER::new($params);
59
60
    return $self;
61
}
62
63
################################################################################
64
=head UI Mapping helper subroutines
65
See. Selenium documentation best practices for UI element mapping to common language descriptions.
66
=cut
67
################################################################################
68
69
sub _getPasswordLoginElements {
70
    my ($self) = @_;
71
    my $d = $self->getDriver();
72
73
    my $submitButton  = $d->find_element('form#auth input[type="submit"]');
74
    my $useridInput   = $d->find_element('#userid');
75
    my $passwordInput = $d->find_element('#password');
76
    return ($submitButton, $useridInput, $passwordInput);
77
}
78
79
80
81
################################################################################
82
=head PageObject Services
83
84
=cut
85
################################################################################
86
87
=head isPasswordLoginAvailable
88
89
    $page->isPasswordLoginAvailable();
90
91
@RETURN t::lib::Page-object
92
@CROAK if password login is unavailable.
93
=cut
94
95
sub isPasswordLoginAvailable {
96
    my $self = shift;
97
    my $d = $self->getDriver();
98
    $self->debugTakeSessionSnapshot();
99
100
    $self->_getPasswordLoginElements();
101
    ok(1, "OpacMain PasswordLogin available");
102
    return $self;
103
}
104
105
sub doPasswordLogin {
106
    my ($self, $username, $password) = @_;
107
    my $d = $self->getDriver();
108
    $self->debugTakeSessionSnapshot();
109
110
    my ($submitButton, $useridInput, $passwordInput) = $self->_getPasswordLoginElements();
111
    $useridInput->send_keys($username);
112
    $passwordInput->send_keys($password);
113
    $submitButton->click();
114
    $self->debugTakeSessionSnapshot();
115
116
    my $cookies = $d->get_all_cookies();
117
    my @cgisessid = grep {$_->{name} eq 'CGISESSID'} @$cookies;
118
119
    my $loggedinusernameSpan = $d->find_element('span.loggedinusername');
120
    ok(($cgisessid[0]), "OpacMain PasswordLogin succeeded"); #We have the element && Cookie CGISESSID defined!
121
122
    return t::lib::Page::Opac::OpacUser->rebrandFromPageObject($self);
123
}
124
125
1; #Make the compiler happy!
(-)a/t/lib/Page/Opac/OpacMemberentry.pm (+161 lines)
Line 0 Link Here
1
package t::lib::Page::Opac::OpacMemberentry;
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public Lice strongnse
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Scalar::Util qw(blessed);
22
use Test::More;
23
24
use t::lib::Page::Opac::OpacUser;
25
26
use base qw(t::lib::Page::Opac t::lib::Page::Opac::LeftNavigation);
27
28
use Koha::Exception::BadParameter;
29
30
=head NAME t::lib::Page::Opac::OpacMemberentry
31
32
=head SYNOPSIS
33
34
PageObject providing page functionality as a service!
35
36
=cut
37
38
=head new
39
40
    my $opacmemberentry = t::lib::Page::Opac::OpacMemberentry->new();
41
42
Instantiates a WebDriver and loads the opac/opac-memberentry.pl.
43
@PARAM1 HASHRef of optional and MANDATORY parameters
44
MANDATORY extra parameters:
45
    none atm.
46
47
@RETURNS t::lib::Page::Opac::OpacMemberentry, ready for user actions!
48
=cut
49
50
sub new {
51
    my ($class, $params) = @_;
52
    unless (ref($params) eq 'HASH' || (blessed($params) && $params->isa('t::lib::Page') )) {
53
        $params = {};
54
    }
55
    $params->{resource} = '/cgi-bin/koha/opac-memberentry.pl';
56
    $params->{type}     = 'opac';
57
58
    my $self = $class->SUPER::new($params);
59
60
    return $self;
61
}
62
63
################################################################################
64
=head UI Mapping helper subroutines
65
See. Selenium documentation best practices for UI element mapping to common language descriptions.
66
=cut
67
################################################################################
68
69
sub _getInputFieldsForValidation {
70
    my ($self) = @_;
71
    my $d = $self->getDriver();
72
73
    my $emailInput  = $d->find_element('#borrower_email');
74
    my $emailProInput  = $d->find_element('#borrower_emailpro');
75
    my $email_BInput  = $d->find_element('#borrower_B_email');
76
77
    my $phoneInput  = $d->find_element('#borrower_phone');
78
    my $phoneProInput  = $d->find_element('#borrower_phonepro');
79
    my $phone_BInput  = $d->find_element('#borrower_B_phone');
80
81
    return ($emailInput, $emailProInput, $email_BInput, $phoneInput, $phoneProInput, $phone_BInput);
82
}
83
84
85
################################################################################
86
=head PageObject Services
87
88
=cut
89
################################################################################
90
91
=head isFieldsAvailable
92
93
    $page->isFieldsAvailable();
94
95
@RETURN t::lib::Page-object
96
@CROAK if unable to find required fields.
97
=cut
98
99
sub setEmail {
100
    my ($self, $input) = @_;
101
    my $d = $self->getDriver();
102
    $self->debugTakeSessionSnapshot();
103
104
    my ($emailInput, $emailProInput, $email_BInput, $phoneInput, $phoneProInput, $phone_BInput) = $self->_getInputFieldsForValidation();
105
106
    $emailInput->send_keys($input);
107
    $emailProInput->send_keys($input);
108
    $email_BInput->send_keys($input);
109
    ok(1, "OpacMemberentry Wrote \"$input\" to email fields.");
110
111
    return $self;
112
}
113
114
sub setPhone {
115
    my ($self, $input) = @_;
116
    my $d = $self->getDriver();
117
    $self->debugTakeSessionSnapshot();
118
119
    my ($emailInput, $emailProInput, $email_BInput, $phoneInput, $phoneProInput, $phone_BInput) = $self->_getInputFieldsForValidation();
120
121
    $phoneInput->send_keys($input);
122
    $phoneProInput->send_keys($input);
123
    $phone_BInput->send_keys($input);
124
    ok(1, "OpacMemberentry Wrote \"$input\" to phone fields.");
125
126
    return $self;
127
}
128
129
sub submitForm {
130
    my ($self, $valid) = @_;
131
    my $d = $self->getDriver();
132
    $self->debugTakeSessionSnapshot();
133
134
    my $submitButton = $d->find_element('form#memberentry-form input[type="submit"]');
135
    $submitButton->click();
136
137
    $self->debugTakeSessionSnapshot();
138
139
    if ($valid) {
140
        my $submitted = $d->find_element('#update-submitted');
141
        ok(1, "OpacMemberentry Submit changes success");
142
    } else {
143
        my @notsubmitted = $d->find_elements('form#memberentry-form label[id^="borrower_"][id$="-error"]', 'css');
144
        my $error_ids = "";
145
146
        foreach my $el_id (@notsubmitted){
147
            my $attr_id = $el_id->get_attribute("id");
148
            $attr_id =~ s/borrower_//g;
149
            $attr_id =~ s/-error//g;
150
            $error_ids .=  "'".$attr_id . "' ";
151
        }
152
153
        ok(1, "OpacMemberentry Submit changes ". $error_ids .", validation error (as expected).");
154
    }
155
156
157
158
    return t::lib::Page::Opac::OpacUser->rebrandFromPageObject($self);
159
}
160
161
1;
(-)a/t/lib/Page/Opac/OpacMessaging.pm (+101 lines)
Line 0 Link Here
1
package t::lib::Page::Opac::OpacMessaging;
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public Lice strongnse
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Scalar::Util qw(blessed);
22
use Test::More;
23
24
use t::lib::Page::Opac::OpacUser;
25
26
use base qw(t::lib::Page::Opac t::lib::Page::Opac::LeftNavigation);
27
28
use Koha::Exception::BadParameter;
29
30
=head NAME t::lib::Page::Opac::OpacMessaging
31
32
=head SYNOPSIS
33
34
PageObject providing page functionality as a service!
35
36
=cut
37
38
=head new
39
40
    my $opacmemberentry = t::lib::Page::Opac::OpacMessaging->new();
41
42
Instantiates a WebDriver and loads the opac/opac-messaging.pl.
43
@PARAM1 HASHRef of optional and MANDATORY parameters
44
MANDATORY extra parameters:
45
    none atm.
46
47
@RETURNS t::lib::Page::Opac::OpacMessaging, ready for user actions!
48
=cut
49
50
sub new {
51
    my ($class, $params) = @_;
52
    unless (ref($params) eq 'HASH' || (blessed($params) && $params->isa('t::lib::Page') )) {
53
        $params = {};
54
    }
55
    $params->{resource} = '/cgi-bin/koha/opac-messaging.pl';
56
    $params->{type}     = 'opac';
57
58
    my $self = $class->SUPER::new($params);
59
60
    return $self;
61
}
62
63
sub _getMessagingPreferenceCheckboxes {
64
    my ($self) = @_;
65
    my $d = $self->getDriver();
66
67
    my @email_prefs = $d->find_elements('input[type="checkbox"][id^="email"]');
68
    my @phone_prefs = $d->find_elements('input[type="checkbox"][id^="phone"]');
69
    my @sms_prefs = $d->find_elements('input[type="checkbox"][id^="sms"]');
70
71
    return  { email => \@email_prefs, phone => \@phone_prefs, sms => \@sms_prefs };
72
}
73
74
################################################################################
75
=head UI Mapping helper subroutines
76
See. Selenium documentation best practices for UI element mapping to common language descriptions.
77
=cut
78
################################################################################
79
80
sub checkMessagingPreferencesSet {
81
    my ($self, $valid, @prefs) = @_;
82
    my $d = $self->getDriver();
83
    $self->debugTakeSessionSnapshot();
84
85
    foreach my $type (@prefs){
86
        my @this_pref = $d->find_elements('input[type="checkbox"][id^="'.$type.'"]');
87
88
        my $ok = 0;
89
90
        foreach my $checkbox (@this_pref){
91
            ok(0, "Opac Messaging $type checkbox ".$checkbox->get_attribute('id')." not checked") if !$checkbox->is_selected() and $valid;
92
            ok(0, "Opac Messaging $type checkbox ".$checkbox->get_attribute('id')." checked (not supposed to be)") if $checkbox->is_selected() and !$valid;
93
            $ok = 1;
94
        }
95
        ok($ok, "Opac Messaging $type checkboxes ok (all " . (($valid) ? 'checked':'unchecked') . ")");
96
    }
97
98
    return $self;
99
}
100
101
1;
(-)a/t/lib/Page/Opac/OpacPaycollect.pm (+94 lines)
Line 0 Link Here
1
package t::lib::Page::Opac::OpacPaycollect;
2
3
# Copyright 2016 KohaSuomi
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public Lice strongnse
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Scalar::Util qw(blessed);
22
use Test::More;
23
24
use t::lib::Page::Opac::OpacPaycollect;
25
26
use base qw(t::lib::Page::Opac t::lib::Page::Opac::LeftNavigation);
27
28
use Koha::Exception::BadParameter;
29
30
=head NAME t::lib::Page::Opac::OpacPaycollect
31
32
=head SYNOPSIS
33
34
PageObject providing page functionality as a service!
35
36
=cut
37
38
=head new
39
40
    my $opacpaycollect = t::lib::Page::Opac::OpacPaycollect->new();
41
42
Instantiates a WebDriver and loads the opac/opac-paycollect.pl.
43
@PARAM1 HASHRef of optional and MANDATORY parameters
44
MANDATORY extra parameters:
45
    none atm.
46
47
@RETURNS t::lib::Page::Opac::OpacPaycollect, ready for user actions!
48
=cut
49
50
sub new {
51
    my ($class, $params) = @_;
52
    unless (ref($params) eq 'HASH' || (blessed($params) && $params->isa('t::lib::Page') )) {
53
        $params = {};
54
    }
55
    $params->{resource} = '/cgi-bin/koha/opac-paycollect.pl';
56
    $params->{type}     = 'opac';
57
58
    my $self = $class->SUPER::new($params);
59
60
    return $self;
61
}
62
63
################################################################################
64
=head UI Mapping helper subroutines
65
See. Selenium documentation best practices for UI element mapping to common language descriptions.
66
=cut
67
################################################################################
68
69
sub isPreparing {
70
    my ($self, $status) = @_;
71
    my $d = $self->getDriver();
72
    $self->debugTakeSessionSnapshot();
73
74
    my $h3 = $d->find_element("//h3[contains(.,\"Preparing to pay fines\")]",'xpath');
75
    is($h3->get_text(), "Preparing to pay fines", "Opac preparing to redirect user to online shop (but skipping online shop in these tests)");
76
    my $continueLink = $d->find_element("//p[contains(.,\"automatically redirected to\")]/a[text()=\"online payment\"]", "xpath");
77
78
    $continueLink->click();
79
    ok(1, "Opac Clicked to continue with the payment");
80
81
    return $self;
82
}
83
84
sub isPaymentPaid {
85
    my ($self, $status) = @_;
86
    my $d = $self->getDriver();
87
    $self->debugTakeSessionSnapshot();
88
89
    my $h3 = $d->find_element("//h3[contains(.,\"You have no outstanding\")]",'xpath');
90
    ok(1, "Opac Skipped online store. No outstanding fines");
91
92
    return $self;
93
}
94
1;
(-)a/t/lib/Page/Opac/OpacSearch.pm (+142 lines)
Line 0 Link Here
1
package t::lib::Page::Opac::OpacSearch;
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Scalar::Util qw(blessed);
22
use Test::More;
23
24
use t::lib::Page::PageUtils;
25
use t::lib::Page::Opac::OpacMain;
26
use t::lib::Page::Opac::OpacSearchHistory;
27
28
use base qw(t::lib::Page::Opac);
29
30
use Koha::Exception::BadParameter;
31
32
=head NAME t::lib::Page::Opac::OpacSearch
33
34
=head SYNOPSIS
35
36
PageObject providing page functionality as a service!
37
38
=cut
39
40
=head new
41
42
    my $opacsearch = t::lib::Page::Opac::OpacSearch->new();
43
44
Instantiates a WebDriver and loads the opac/opac-search.pl.
45
@PARAM1 HASHRef of optional and MANDATORY parameters
46
MANDATORY extra parameters:
47
    none atm.
48
49
@RETURNS t::lib::Page::Opac::OpacSearch, ready for user actions!
50
=cut
51
52
sub new {
53
    my ($class, $params) = @_;
54
    unless (ref($params) eq 'HASH' || (blessed($params) && $params->isa('t::lib::Page') )) {
55
        $params = {};
56
    }
57
    $params->{resource} = '/cgi-bin/koha/opac-search.pl';
58
    $params->{type}     = 'opac';
59
60
    my $self = $class->SUPER::new($params);
61
62
    return $self;
63
}
64
65
66
################################################################################
67
=head UI Mapping helper subroutines
68
See. Selenium documentation best practices for UI element mapping to common language descriptions.
69
=cut
70
################################################################################
71
72
sub _findSearchFieldElements {
73
    my ($self, $searchField) = @_;
74
    my $d = $self->getDriver();
75
    $searchField = '0' unless $searchField;
76
77
    my $indexSelect = $d->find_element("#search-field_$searchField");
78
    my $termInput = $d->find_element("#search-field_$searchField + input[name='q']");
79
    my $searchSubmit = $d->find_element("input[type='submit'].btn-success"); #Returns the first instance.
80
    return ($indexSelect, $termInput, $searchSubmit);
81
}
82
83
84
85
################################################################################
86
=head PageObject Services
87
88
=cut
89
################################################################################
90
91
=head doSetSearchFieldTerm
92
93
Sets the search index and term for one of the (by default) three search fields.
94
@PARAM1, Integer, which search field to put the parameters into?
95
                  Starts from 0 == the topmost search field.
96
@PARAM2, String, the index to use. Undef if you want to use whatever there is.
97
                 Use the english index full name, eg. "Keyword", "Title", "Author".
98
@PARAM3, String, the search term. This replaces any existing search terms in the search field.
99
=cut
100
101
sub doSetSearchFieldTerm {
102
    my ($self, $searchField, $selectableIndex, $term) = @_;
103
    $searchField = '0' unless $searchField; #Trouble with Perl interpreting 0
104
    my $d = $self->getDriver();
105
    $self->debugTakeSessionSnapshot();
106
107
    my ($indexSelect, $termInput, $searchSubmit) = $self->_findSearchFieldElements($searchField);
108
109
    if ($selectableIndex) {
110
        t::lib::Page::PageUtils::displaySelectsOptions($d, $indexSelect);
111
        my $optionElement = t::lib::Page::PageUtils::getSelectElementsOptionByName($d, $indexSelect, $selectableIndex);
112
        $optionElement->click();
113
    }
114
115
    if ($term) {
116
        $termInput->clear();
117
        $termInput->send_keys($term);
118
    }
119
    else {
120
        Koha::Exception::BadParameter->throw("doSetSearchFieldTerm():> Parameter \$main is mandatory but is missing? Parameters as follow\n: @_");
121
    }
122
123
    $selectableIndex = '' unless $selectableIndex;
124
    ok(1, "SearchField parameters '$selectableIndex' and '$term' set.");
125
    $self->debugTakeSessionSnapshot();
126
    return $self;
127
}
128
129
sub doSearchSubmit {
130
    my ($self) = @_;
131
    my $d = $self->getDriver();
132
    $self->debugTakeSessionSnapshot();
133
134
    my ($indexSelect, $termInput, $searchSubmit) = $self->_findSearchFieldElements(0); #We just want the submit button
135
    $searchSubmit->click();
136
    $self->debugTakeSessionSnapshot();
137
138
    ok(($d->get_title() =~ /Results of search/), "SearchField search.");
139
    return $self;
140
}
141
142
1; #Make the compiler happy!
(-)a/t/lib/Page/Opac/OpacSearchHistory.pm (+121 lines)
Line 0 Link Here
1
package t::lib::Page::Opac::OpacSearchHistory;
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Test::More;
22
23
use base qw(t::lib::Page::Opac t::lib::Page::Opac::LeftNavigation);
24
25
use Koha::Exception::FeatureUnavailable;
26
27
=head NAME t::lib::Page::Opac::OpacSearchHistory
28
29
=head SYNOPSIS
30
31
PageObject providing page functionality as a service!
32
33
=cut
34
35
=head new
36
37
YOU CANNOT GET HERE WITHOUT LOGGING IN FIRST!
38
39
=cut
40
41
sub new {
42
    Koha::Exception::FeatureUnavailable->throw(error => __PACKAGE__."->new():> You must login first to navigate to this page!");
43
}
44
45
################################################################################
46
=head UI Mapping helper subroutines
47
See. Selenium documentation best practices for UI element mapping to common language descriptions.
48
=cut
49
################################################################################
50
51
sub _getAllSearchHistories {
52
    my ($self) = @_;
53
    my $d = $self->getDriver();
54
55
    $self->pause(500); #Wait for datatables to load the page.
56
    my $histories = $d->find_elements("table.historyt tr");
57
    #First index has the table header, so skip that.
58
    shift @$histories;
59
    for (my $i=0 ; $i<scalar(@$histories) ; $i++) {
60
        $histories->[$i] = $self->_castSearchHistoryRowToHash($histories->[$i]);
61
    }
62
    return $histories;
63
}
64
65
66
67
################################################################################
68
=head PageObject Services
69
70
=cut
71
################################################################################
72
73
=head testDoSearchHistoriesExist
74
75
    $opacsearchhistory->testDoSearchHistoriesExist([ 'maximus',
76
                                                     'julius',
77
                                                     'titus',
78
                                                  ]);
79
@PARAM1 ARRAYRef of search strings shown in the opac-search-history.pl -page.
80
                 These search strings need only be contained in the displayed values.
81
=cut
82
83
sub testDoSearchHistoriesExist {
84
    my ($self, $searchStrings) = @_;
85
    my $d = $self->getDriver();
86
    $self->debugTakeSessionSnapshot();
87
88
    my $histories = $self->_getAllSearchHistories();
89
    foreach my $s (@$searchStrings) {
90
91
        my $matchFound;
92
        foreach my $h (@$histories) {
93
            if ($h->{searchStringA}->get_text() =~ /$s/) {
94
                $matchFound = $h->{searchStringA}->get_text();
95
                last();
96
            }
97
        }
98
        ok($matchFound =~ /$s/, "SearchHistory $s exists.");
99
    }
100
    return $self;
101
}
102
103
sub _castSearchHistoryRowToHash {
104
    my ($self, $historyRow) = @_;
105
    my $d = $self->getDriver();
106
107
    my $checkbox = $d->find_child_element($historyRow, "input[type='checkbox']","css");
108
    my $date = $d->find_child_element($historyRow, "span[title]","css");
109
    $date = $date->get_text();
110
    my $searchStringA = $d->find_child_element($historyRow, "a + a","css");
111
    my $resultsCount = $d->find_child_element($historyRow, "td + td + td + td","css");
112
113
    my $sh = {  checkbox => $checkbox,
114
                date => $date,
115
                searchStringA => $searchStringA,
116
                resultsCount => $resultsCount,
117
              };
118
    return $sh;
119
}
120
121
1; #Make the compiler happy!
(-)a/t/lib/Page/Opac/OpacUser.pm (+64 lines)
Line 0 Link Here
1
package t::lib::Page::Opac::OpacUser;
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use base qw(t::lib::Page::Opac t::lib::Page::Opac::LeftNavigation);
23
24
use Koha::Exception::FeatureUnavailable;
25
26
=head NAME t::lib::Page::Opac::OpacUser
27
28
=head SYNOPSIS
29
30
PageObject providing page functionality as a service!
31
32
=cut
33
34
=head new
35
36
YOU CANNOT GET HERE WITHOUT LOGGING IN FIRST!
37
Navigate here from opac-main.pl for example.
38
=cut
39
40
sub new {
41
    Koha::Exception::FeatureUnavailable->throw(error => __PACKAGE__."->new():> You must login first to navigate to this page!");
42
}
43
44
################################################################################
45
=head UI Mapping helper subroutines
46
See. Selenium documentation best practices for UI element mapping to common language descriptions.
47
=cut
48
################################################################################
49
50
51
52
53
54
################################################################################
55
=head PageObject Services
56
57
=cut
58
################################################################################
59
60
61
62
63
64
1; #Make the compiler happy!
(-)a/t/lib/Page/PageUtils.pm (-1 / +69 lines)
Line 0 Link Here
0
- 
1
package t::lib::Page::PageUtils;
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use Koha::Exception::UnknownObject;
23
24
=head NAME t::lib::Page::PageUtils
25
26
=head SYNOPSIS
27
28
Contains all kinds of helper functions used all over the PageObject testing framework.
29
30
=cut
31
32
sub getSelectElementsOptionByName {
33
    my ($d, $selectElement, $optionName) = @_;
34
35
    my $options = $d->find_child_elements($selectElement, "option", 'css');
36
    my $correctOption;
37
    foreach my $option (@$options) {
38
        if ($option->get_text() eq $optionName) {
39
            $correctOption = $option;
40
            last();
41
        }
42
    }
43
44
    return $correctOption if $correctOption;
45
46
    ##Throw Exception because we didn't find the option element.
47
    my @availableOptions;
48
    foreach my $option (@$options) {
49
        push @availableOptions, $option->get_tag_name() .', value: '. $option->get_value() .', text: '. $option->get_text();
50
    }
51
    Koha::Exception::UnknownObject->throw(error =>
52
        "getSelectElementsOptionByName():> Couldn't find the given option-element using '$optionName'. Available options:\n".
53
        join("\n", @availableOptions));
54
}
55
56
sub displaySelectsOptions {
57
    my ($d, $selectElement) = @_;
58
59
    my $options = $d->find_child_elements($selectElement, "option", 'css');
60
    if (scalar(@$options)) {
61
        $selectElement->click() if $options->[0]->is_hidden();
62
    }
63
    else {
64
        Koha::Exception::UnknownObject->throw(error =>
65
            "_displaySelectsOptions():> element: ".$selectElement->get_tag_name()-', class: '.$selectElement->get_attribute("class").", doesn't have any option-elements?");
66
    }
67
}
68
69
1;

Return to bug 14536