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

(-)a/misc/devel/interactiveWebDriverShell.pl (+190 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/member-flags.pl" =>
122
    {   package     => "t::lib::Page::Members::MemberFlags",
123
        urlEndpoint => "members/member-flags.pl",
124
        status      => "not implemented",
125
        params      => ["borrowernumber"],
126
    },
127
################################################################################
128
  ########## OPAC CONFIGURATIONS ##########
129
################################################################################
130
    "opac/opac-main.pl" =>
131
    {   package     => "t::lib::Page::Opac::OpacMain",
132
        urlEndpoint => "opac/opac-main.pl",
133
        status      => "OK",
134
    },
135
};
136
################################################################################
137
  ########## END OF PAGE CONFIGURATIONS ##########
138
################################################################################
139
140
listSupportedPageObjects ($supportedPageObjects) if $list;
141
my ($po, $d) = deployPageObject($supportedPageObjects, $page, \@params, \@login) if $page;
142
143
144
145
print "--Debugging--\n";
146
$DB::single = 1; #Breakpoint here
147
$DB::single = 1;
148
149
150
151
sub listSupportedPageObjects {
152
    my ($supportedPageObjects) = @_;
153
    print Data::Dumper::Dumper($supportedPageObjects);
154
    exit;
155
}
156
sub deployPageObject {
157
    my ($supportedPageObjects, $page, $params, $login) = @_;
158
159
    ##Find correct PageObject deployment rules
160
    my $pageObjectMapping = $supportedPageObjects->{$page};
161
    die "No PageObject mapped to --page '$page'. See --list to list available PageObjects.\n" unless $pageObjectMapping;
162
163
    ##Dynamically load package
164
    my $package = $pageObjectMapping->{package};
165
    eval "require $package";
166
167
    ##Fill required parameters
168
    my $poParams = {};
169
    if (ref($pageObjectMapping->{params}) eq 'ARRAY') {
170
        foreach my $paramName (@{$pageObjectMapping->{params}}) {
171
            $poParams->{$paramName} = shift(@$params);
172
            die "Insufficient parameters given, parameter '$paramName' unsatisfied.\n" unless $poParams->{$paramName};
173
        }
174
    }
175
176
    ##Check if the status is OK
177
    die "PageObject status for '$page' is not 'OK'. Current status '".$pageObjectMapping->{status}."'.\nPlease implement the missing PageObject.\n" unless $pageObjectMapping->{status} eq 'OK';
178
179
    ##Create PageObject
180
    my $po = $package->new($poParams);
181
182
    ##Password login if desired
183
    eval {
184
       $po->isPasswordLoginAvailable->doPasswordLogin($login->[0], $login->[1]) if scalar(@$login);
185
    }; if ($@) {
186
        print "Password login unavailable.\n";
187
    }
188
189
    return ($po, $po->getDriver());
190
}
(-)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::BorrowerFactory;
28
29
##Setting up the test context
30
my $testContext = {};
31
32
my $password = '1234';
33
my $borrowerFactory = t::lib::TestObjects::BorrowerFactory->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 (+222 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
=cut
97
98
sub rebrandFromPageObject {
99
    my ($class, $self) = @_;
100
    bless($self, $class);
101
    return $self;
102
}
103
104
=head _mergeDefaultConfig
105
106
@THROWS Koha::Exception::BadParameter
107
=cut
108
109
sub _mergeDefaultConfig {
110
    my ($params) = @_;
111
    unless (ref($params) eq 'HASH' && $params->{type}) {
112
        Koha::Exception::BadParameter->throw(error => "t::lib::Page:> When instantiating Page-objects, you must define the 'type'-parameter.");
113
    }
114
115
    my $testServerConfigs = C4::Context->config('testservers');
116
    my $conf = $testServerConfigs->{ $params->{type} };
117
    Koha::Exception::BadParameter->throw(error => "t::lib::Page:> Unknown 'type'-parameter '".$params->{type}."'. Values 'opac', 'staff' and 'rest' are supported.")
118
                unless $conf;
119
    #Merge given $params-config on top of the $KOHA_CONF's testservers-directives
120
    @$conf{keys %$params} = values %$params;
121
    return $conf;
122
}
123
124
=head quit
125
Wrapper for Selenium::Remote::Driver->quit(),
126
Delete the session & close open browsers.
127
128
When ending this browser session, it is polite to quit, or there is a risk of leaving
129
floating test browsers floating around.
130
=cut
131
132
sub quit {
133
    my ($self) = @_;
134
    $self->getDriver()->quit();
135
}
136
137
=head pause
138
Wrapper for Selenium::Remote::Driver->pause(),
139
=cut
140
141
sub pause {
142
    my ($self, $pauseMillis) = @_;
143
    $self->getDriver()->pause($pauseMillis);
144
    return $self;
145
}
146
147
################################################
148
  ##  INTRODUCING OBJECT ACCESSORS  ##
149
################################################
150
sub setDriver {
151
    my ($self, $driver) = @_;
152
    $self->{driver} = $driver;
153
}
154
sub getDriver {
155
    my ($self) = @_;
156
    return $self->{driver};
157
}
158
159
################################################
160
  ##  INTRODUCING TESTING HELPERS  ##
161
################################################
162
sub debugSetEnvironment {
163
    my ($self) = @_;
164
    if ($ENV{KOHA_PAGEOBJECT_DEBUG}) {
165
        $self->{debugSessionId} = sprintf("%03i",rand(999));
166
        $self->{debugSessionTmpDirectory} = "/tmp/PageObjectDebug/";
167
        $self->{debugSessionTmpDirectory} = $ENV{KOHA_PAGEOBJECT_DEBUG} if (not(ref($ENV{KOHA_PAGEOBJECT_DEBUG})) && length($ENV{KOHA_PAGEOBJECT_DEBUG}) > 1);
168
        my $error = system(("mkdir", "-p", $self->{debugSessionTmpDirectory}));
169
        Koha::Exception::SystemCall->throw(error => "Trying to create a temporary directory for PageObject debugging session '".$self->{debugSessionId}."' failed:\n  $?")
170
                if $error;
171
        $self->{debugInternalCounter} = 1;
172
173
        print "\n\n--Starting PageObject debugging session '".$self->{debugSessionId}."'\n\n";
174
    }
175
}
176
177
sub debugTakeSessionSnapshot {
178
    my ($self) = @_;
179
    if ($ENV{KOHA_PAGEOBJECT_DEBUG}) {
180
        my ($actionIdentifier, $actionFile) = $self->_debugGetSessionIdentifier(2);
181
182
        $self->_debugWriteHTML($actionIdentifier, $actionFile);
183
        $self->_debugWriteScreenshot($actionIdentifier, $actionFile);
184
        $self->{debugInternalCounter}++;
185
    }
186
}
187
188
sub _debugGetSessionIdentifier {
189
    my ($self, $callerDepth) = @_;
190
    $callerDepth = $callerDepth || 2;
191
    ##Create a unique and descriptive identifier for this program state.
192
    my ($package, $filename, $line, $subroutine) = caller($callerDepth); #Get where we are called from
193
    $subroutine = $2 if ($subroutine =~ /(::|->)([^:->]+)$/); #Get the last part of the package, the subroutine name.
194
    my $actionIdentifier = "[session '".$self->{debugSessionId}."', counter '".sprintf("%03i",$self->{debugInternalCounter})."', caller '$subroutine']";
195
    my $actionFile = $self->{debugSessionId}.'_'.sprintf("%03i",$self->{debugInternalCounter}).'_'.$subroutine;
196
    return ($actionIdentifier, $actionFile);
197
}
198
199
sub _debugWriteHTML {
200
    require Data::Dumper;
201
    my ($self, $actionIdentifier, $actionFile) = @_;
202
    my $d = $self->getDriver();
203
204
    ##Write the current Response data
205
    open(my $fh, ">:encoding(UTF-8)", $self->{debugSessionTmpDirectory}.$actionFile.'.html')
206
                or die "Trying to open a filehandle for PageObject debugging output $actionIdentifier:\n  $@";
207
    print $fh $d->get_title()."\n";
208
    print $fh "ALL COOKIES DUMP:\n".Data::Dumper::Dumper($d->get_all_cookies());
209
    print $fh $d->get_page_source()."\n";
210
    close $fh;
211
}
212
213
sub _debugWriteScreenshot {
214
    my ($self, $actionIdentifier, $actionFile) = @_;
215
    my $d = $self->getDriver();
216
217
    ##Write a screenshot of the view to file.
218
    my $ok = $d->capture_screenshot($self->{debugSessionTmpDirectory}.$actionFile.'.png');
219
    Koha::Exception::SystemCall->throw(error => "Cannot capture a screenshot for PageObject $actionIdentifier")
220
                unless $ok;
221
}
222
1; #Make the compiler happy!
(-)a/t/lib/Page/Intra.pm (+195 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 _getHeaderElements
47
48
@RETURNS HASHRef of all the Intranet header clickables.
49
=cut
50
51
sub _getHeaderElements {
52
    my ($self) = @_;
53
    my $d = $self->getDriver();
54
55
    my ($patronsA, $searchA, $cartA, $moreA, $drop3A, $helpA);
56
    #Always visible elements
57
    $patronsA = $d->find_element("#header a[href*='members-home.pl']");
58
    $searchA = $d->find_element ("#header a[href*='search.pl']");
59
    $cartA = $d->find_element   ("#header a#cartmenulink");
60
    $moreA = $d->find_element   ("#header a[href='#']");
61
    $drop3A = $d->find_element  ("#header a#drop3");
62
    $helpA = $d->find_element   ("#header a#helper");
63
64
    my $e = {};
65
    $e->{patrons} = $patronsA if $patronsA;
66
    $e->{search} = $searchA if $searchA;
67
    $e->{cart} = $cartA if $cartA;
68
    $e->{more} = $moreA if $moreA;
69
    $e->{drop3} = $drop3A if $drop3A;
70
    $e->{help} = $helpA if $helpA;
71
    return $e;
72
}
73
74
=head _getPasswordLoginElements
75
76
@RETURNS List of Selenium::Remote::Webelement-objects,
77
         ($submitButton, $useridInput, $passwordInput)
78
=cut
79
80
sub _getPasswordLoginElements {
81
    my ($self) = @_;
82
    my $d = $self->getDriver();
83
84
    my $submitButton  = $d->find_element('#submit');
85
    my $useridInput   = $d->find_element('#userid');
86
    my $passwordInput = $d->find_element('#password');
87
    return ($submitButton, $useridInput, $passwordInput);
88
}
89
90
=head _getLoggedInBranchNameElement
91
@RETURNS Selenium::Remote::WebElement matching the <span> containing the currently logged in users branchname
92
=cut
93
94
sub _getLoggedInBranchNameElement {
95
    my ($self) = @_;
96
    my $d = $self->getDriver();
97
    $self->debugTakeSessionSnapshot();
98
99
    my $header = $self->_getHeaderElements();
100
    my $loggedInBranchNameSpan = $d->find_child_element($header->{drop3}, "#logged-in-branch-name", 'css');
101
    return $loggedInBranchNameSpan;
102
}
103
104
=head _getLoggedInBranchCode
105
@RETURNS String, the logged in branch code
106
=cut
107
108
sub _getLoggedInBranchCode {
109
    my ($self) = @_;
110
    my $d = $self->getDriver();
111
    $self->debugTakeSessionSnapshot();
112
113
    #Because the branchcode element is hidden, we need to inject some javascript to get its value since Selenium (t$
114
    my $script = q{
115
        var elem = document.getElementById('logged-in-branch-code').innerHTML;
116
        var callback = arguments[arguments.length-1];
117
        callback(elem);
118
    };
119
    my $loggedInBranchCode = $d->execute_async_script($script);
120
    return $loggedInBranchCode;
121
}
122
123
################################################################################
124
=head PageObject Services
125
126
=cut
127
################################################################################
128
129
=head isPasswordLoginAvailable
130
131
    $page->isPasswordLoginAvailable();
132
133
@RETURN t::lib::Page-object
134
@CROAK if password login is unavailable.
135
=cut
136
137
sub isPasswordLoginAvailable {
138
    my $self = shift;
139
    my $d = $self->getDriver();
140
    $self->debugTakeSessionSnapshot();
141
142
    $self->_getPasswordLoginElements();
143
    ok(($d->get_title() =~ /Log in to Koha/), "Intra PasswordLogin available");
144
    return $self;
145
}
146
147
sub doPasswordLogin {
148
    my ($self, $username, $password) = @_;
149
    my $d = $self->getDriver();
150
    $self->debugTakeSessionSnapshot();
151
152
    my ($submitButton, $useridInput, $passwordInput) = $self->_getPasswordLoginElements();
153
    $useridInput->send_keys($username);
154
    $passwordInput->send_keys($password);
155
    $submitButton->click();
156
    $self->debugTakeSessionSnapshot();
157
158
    my $cookies = $d->get_all_cookies();
159
    my @cgisessid = grep {$_->{name} eq 'CGISESSID'} @$cookies;
160
161
    ok(($d->get_title() !~ /Log in to Koha/ && #No longer in the login page
162
        $d->get_title() !~ /Access denied/ &&
163
        $cgisessid[0]) #Cookie CGISESSID defined!
164
       , "Intra PasswordLogin succeeded");
165
166
    return $self; #After a succesfull password login, we are directed to the same page we tried to access.
167
}
168
169
sub doPasswordLogout {
170
    my ($self, $username, $password) = @_;
171
    my $d = $self->getDriver();
172
    $self->debugTakeSessionSnapshot();
173
174
    #Click the dropdown menu to make the logout-link visible
175
    my $logged_in_identifierA = $d->find_element('#drop3'); #What a nice and descriptive HTML element name!
176
    $logged_in_identifierA->click();
177
178
    #Logout
179
    my $logoutA = $d->find_element('#logout');
180
    $logoutA->click();
181
    $self->debugTakeSessionSnapshot();
182
183
    ok(($d->get_title() =~ /Log in to Koha/), "Intra PasswordLogout succeeded");
184
    return $self; #After a succesfull password logout, we are still in the same page we did before logout.
185
}
186
187
sub isLoggedInBranchCode {
188
    my ($self, $expectedBranchCode) = @_;
189
190
    my $loggedInBranchCode = $self->_getLoggedInBranchCode();
191
    is($expectedBranchCode, $loggedInBranchCode, "#logged-in-branch-code '".$loggedInBranchCode."' matches '$expectedBranchCode'");
192
    return $self;
193
}
194
195
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/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);
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/Moremember.pm (+89 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
23
use base qw(t::lib::Page::Intra);
24
25
use Koha::Exception::BadParameter;
26
27
=head NAME t::lib::Page::Members::Moremember
28
29
=head SYNOPSIS
30
31
moremember.pl PageObject providing page functionality as a service!
32
33
=cut
34
35
=head new
36
37
    my $moremember = t::lib::Page::Members::Moremember->new({borrowernumber => "1"});
38
39
Instantiates a WebDriver and loads the members/moremember.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::Moremember, 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/members/moremember.pl';
53
    $params->{type}     = 'staff';
54
55
    $params->{getParams} = [];
56
    #Handle MANDATORY parameters
57
    if ($params->{borrowernumber}) {
58
        push @{$params->{getParams}}, "borrowernumber=".$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
76
77
78
79
################################################################################
80
=head PageObject Services
81
82
=cut
83
################################################################################
84
85
86
87
88
89
1; #Make the compiler happy!
(-)a/t/lib/Page/Opac.pm (+223 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 doPasswordLogout {
164
    my ($self, $username, $password) = @_;
165
    my $d = $self->getDriver();
166
    $self->debugTakeSessionSnapshot();
167
168
    #Logout
169
    my $headerElements = $self->_getHeaderRegionActionElements();
170
    my $logoutA = $headerElements->{logout};
171
    $logoutA->click();
172
    $self->debugTakeSessionSnapshot();
173
174
    $headerElements = $self->_getHeaderRegionActionElements(); #Take the changed header elements
175
    my $txt = $headerElements->{login}->get_text();
176
    ok(($headerElements->{login}->get_text() =~ /Log in/ ||
177
        $d->get_title() =~ /Log in to your account/), "Opac Header PasswordLogout succeeded");
178
    return t::lib::Page::Opac::OpacMain->rebrandFromPageObject($self);
179
        ok((), "PasswordLogout succeeded");
180
    return t::lib::Page::Opac::OpacMain->rebrandFromPageObject($self);
181
}
182
183
sub navigateSearchHistory {
184
    my ($self) = @_;
185
    my $d = $self->getDriver();
186
    $self->debugTakeSessionSnapshot();
187
188
    my $headerElements = $self->_getHeaderRegionActionElements();
189
    my $searchHistoryA = $headerElements->{searchHistory};
190
    $searchHistoryA->click();
191
    $self->debugTakeSessionSnapshot();
192
193
    ok(($d->get_title() =~ /Your search history/), "Opac Navigation to search history.");
194
    return t::lib::Page::Opac::OpacSearchHistory->rebrandFromPageObject($self);
195
}
196
197
sub navigateAdvancedSearch {
198
    my ($self) = @_;
199
    my $d = $self->getDriver();
200
    $self->debugTakeSessionSnapshot();
201
202
    my ($advancedSearchA, $authoritySearchA, $tagCloudA) = $self->_getMoresearchesElements();
203
    $advancedSearchA->click();
204
205
    $self->debugTakeSessionSnapshot();
206
    ok(($d->get_title() =~ /Advanced search/), "Opac Navigating to advanced search.");
207
    return t::lib::Page::Opac::OpacSearch->rebrandFromPageObject($self);
208
}
209
210
sub navigateHome {
211
    my ($self) = @_;
212
    my $d = $self->getDriver();
213
    $self->debugTakeSessionSnapshot();
214
215
    my $breadcrumbLinks = $self->_getBreadcrumbLinks();
216
    $breadcrumbLinks->[0]->click();
217
218
    $self->debugTakeSessionSnapshot();
219
    ok(($d->get_current_url() =~ /opac-main\.pl/), "Opac Navigating to OPAC home.");
220
    return t::lib::Page::Opac::OpacMain->rebrandFromPageObject($self);
221
}
222
223
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/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);
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);
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