Commit 9b6ec1f5 authored by David Lawrence's avatar David Lawrence

Bug 1069799 - move the QA repository into the main repository

r=LpSolit
parent 6f70920f
...@@ -41,11 +41,6 @@ if [ "$TEST_SUITE" = "docs" ]; then ...@@ -41,11 +41,6 @@ if [ "$TEST_SUITE" = "docs" ]; then
exit $? exit $?
fi fi
echo -e "\n== Cloning QA test suite"
cd $BUGZILLA_ROOT
echo "Cloning git repo $GITHUB_QA_GIT branch $GITHUB_BASE_BRANCH ..."
git clone $GITHUB_QA_GIT -b $GITHUB_BASE_BRANCH qa
echo -e "\n== Starting database" echo -e "\n== Starting database"
/usr/bin/mysqld_safe & /usr/bin/mysqld_safe &
sleep 3 sleep 3
...@@ -55,32 +50,24 @@ echo -e "\n== Starting memcached" ...@@ -55,32 +50,24 @@ echo -e "\n== Starting memcached"
sleep 3 sleep 3
echo -e "\n== Updating configuration" echo -e "\n== Updating configuration"
sed -e "s?%DB%?$BUGS_DB_DRIVER?g" --in-place qa/config/checksetup_answers.txt sed -e "s?%DB%?$BUGS_DB_DRIVER?g" --in-place xt/config/checksetup_answers.txt
sed -e "s?%DB_NAME%?bugs_test?g" --in-place qa/config/checksetup_answers.txt echo "\$answer{'memcached_servers'} = 'localhost:11211';" >> xt/config/checksetup_answers.txt
sed -e "s?%USER%?$USER?g" --in-place qa/config/checksetup_answers.txt
sed -e "s?%TRAVIS_BUILD_DIR%?$BUGZILLA_ROOT?g" --in-place qa/config/selenium_test.conf
echo "\$answer{'memcached_servers'} = 'localhost:11211';" >> qa/config/checksetup_answers.txt
if [ "$TEST_SUITE" == "checksetup" ]; then
cd $BUGZILLA_ROOT/qa
/bin/bash /docker_files/buildbot_step "Checksetup" ./test_checksetup.pl config/config-checksetup-$BUGS_DB_DRIVER
exit $?
fi
echo -e "\n== Running checksetup" echo -e "\n== Running checksetup"
cd $BUGZILLA_ROOT cd $BUGZILLA_ROOT
./checksetup.pl qa/config/checksetup_answers.txt ./checksetup.pl xt/config/checksetup_answers.txt
./checksetup.pl qa/config/checksetup_answers.txt ./checksetup.pl xt/config/checksetup_answers.txt
echo -e "\n== Generating test data" echo -e "\n== Generating test data"
cd $BUGZILLA_ROOT/qa/config cd $BUGZILLA_ROOT/xt/config
perl -I../../local/lib/perl5 generate_test_data.pl perl generate_test_data.pl
echo -e "\n== Starting web server" echo -e "\n== Starting web server"
sed -e "s?^#Perl?Perl?" --in-place /etc/httpd/conf.d/bugzilla.conf sed -e "s?^#Perl?Perl?" --in-place /etc/httpd/conf.d/bugzilla.conf
/usr/sbin/httpd & /usr/sbin/httpd &
sleep 3 sleep 3
cd $BUGZILLA_ROOT
if [ "$TEST_SUITE" = "selenium" ]; then if [ "$TEST_SUITE" = "selenium" ]; then
export DISPLAY=:0 export DISPLAY=:0
...@@ -100,13 +87,11 @@ if [ "$TEST_SUITE" = "selenium" ]; then ...@@ -100,13 +87,11 @@ if [ "$TEST_SUITE" = "selenium" ]; then
# but no tests actually executed. # but no tests actually executed.
[ $NO_TESTS ] && exit 0 [ $NO_TESTS ] && exit 0
cd $BUGZILLA_ROOT/qa/t /bin/bash /docker_files/buildbot_step "Selenium" prove -f -v xt/selenium/*.t
/bin/bash /docker_files/buildbot_step "Selenium" prove -f -v -I$BUGZILLA_ROOT/lib test_*.t
exit $? exit $?
fi fi
if [ "$TEST_SUITE" = "webservices" ]; then if [ "$TEST_SUITE" = "webservices" ]; then
cd $BUGZILLA_ROOT/qa/t /bin/bash /docker_files/buildbot_step "Webservices" prove -f -v xt/{rest,webservice}/*.t
/bin/bash /docker_files/buildbot_step "Webservices" prove -f -v -I$BUGZILLA_ROOT/lib {rest,webservice}_*.t
exit $? exit $?
fi fi
...@@ -28,7 +28,7 @@ foreach my $extension (@extensions) { ...@@ -28,7 +28,7 @@ foreach my $extension (@extensions) {
find(sub { push(@files, $File::Find::name) if $_ =~ /\.pm$/;}, $extension); find(sub { push(@files, $File::Find::name) if $_ =~ /\.pm$/;}, $extension);
} }
our @test_files = glob('t/*.t'); our @test_files = glob('t/*.t xt/*/*.t');
sub isTestingFile { sub isTestingFile {
my ($file) = @_; my ($file) = @_;
......
The tests in this directory require a working database, as opposed
to the tests in t/, which simply test the code without a working
installation.
Some of the tests may modify your current working installation, even
if only temporarily. To run the tests that modify your database,
set the environment variable BZ_WRITE_TESTS to 1.
Some tests also take additional, optional arguments. You can pass arguments
to tests like:
prove xt/search.t :: --long --operators=equals,notequals
Note the "::"--that is necessary to note that the arguments are going to
the test, not to "prove".
See the perldoc of the individual tests to see what options they support,
or do "perl xt/search.t --help".
$answer{'db_host'} = 'localhost';
$answer{'db_driver'} = '%DB%';
$answer{'db_port'} = 0;
$answer{'db_name'} = 'bugs_test',
$answer{'db_user'} = 'bugs';
$answer{'db_pass'} = 'bugs';
$answer{'db_sock'} = '';
$answer{'db_check'} = 1;
$answer{'db_mysql_ssl_ca_file'} = '';
$answer{'db_mysql_ssl_ca_path'} = '';
$answer{'db_mysql_ssl_client_cert'} = '';
$answer{'db_mysql_ssl_client_key'} = '';
$answer{'urlbase'} = 'http://localhost/bugzilla/';
$answer{'create_htaccess'} = '';
$answer{'use_suexec'} = '';
$answer{'index_html'} = 0;
$answer{'cvsbin'} = '/usr/bin/cvs';
$answer{'interdiffbin'} = '/usr/bin/interdiff';
$answer{'diffpath'} = '/usr/bin';
$answer{'webservergroup'} = 'bugzilla';
$answer{'ADMIN_OK'} = 'Y';
$answer{'ADMIN_EMAIL'} = 'admin@bugzilla.org';
$answer{'ADMIN_PASSWORD'} = 'password';
$answer{'ADMIN_REALNAME'} = 'QA Admin';
$answer{'NO_PAUSE'} = 1;
Index: Bugzilla/Config/MTA.pm
===================================================================
RCS file: /cvsroot/mozilla/webtools/bugzilla/Bugzilla/Config/MTA.pm,v
retrieving revision 1.13
diff -3 -p -u -r1.13 MTA.pm
--- Bugzilla/Config/MTA.pm 13 Nov 2006 23:32:28 -0000 1.13
+++ Bugzilla/Config/MTA.pm 9 Dec 2006 12:19:44 -0000
@@ -44,7 +44,9 @@ sub get_param_list {
{
name => 'mail_delivery_method',
type => 's',
- choices => [Email::Send->new()->all_mailers(), 'None'],
+ # Bugzilla is not ready yet to send mails to newsgroups, and 'IO'
+ # is of no use for now as we already have our own 'Test' mode.
+ choices => [grep {$_ ne 'NNTP' && $_ ne 'IO'} Email::Send->new()->all_mailers(), 'None'],
default => 'Sendmail',
checker => \&check_mail_delivery_method
},
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
# To make this configuration file useful to you, you have to:
# - set the path and URL to your Bugzilla installation.
# - replace @my.company by something more relevant to you,
# also what comes before @my.company if you want/need to.
# - set passwords for each user accounts.
{ 'browser' => '*firefox',
'experimental_browser_launcher' => '*chrome',
'host' => 'localhost',
'port' => 4444,
'browser_url' => 'http://localhost',
'attachment_file' => '/home/bugzilla/devel/htdocs/bugzilla/xt/config/patch.diff',
'bugzilla_installation' => 'bugzilla',
'bugzilla_path' => '/home/bugzilla/devel/htdocs/bugzilla',
'admin_user_login' => 'admin@my.company',
'admin_user_passwd' => '******',
'admin_user_username' => 'admin',
'admin_user_api_key' => 'zQ5TSBzq7tTZMtKYq9K1ZqJMjifKx3cPL7pIGk9Q',
'permanent_user' => 'permanent_user@my.company',
'unprivileged_user_login' => 'no-privs@my.company',
'unprivileged_user_passwd' => '******',
'unprivileged_user_username' => 'no-privs',
'unprivileged_user_login_truncated' => 'no-privs@my',
'unprivileged_user_api_key' => 'zQ5TSBzqP4nrdBKYq9Re4qJrjifKx3cK07pIGk9Q',
'QA_Selenium_TEST_user_login' => 'QA-Selenium-TEST@my.company',
'QA_Selenium_TEST_user_passwd' => '******',
'editbugs_user_login' => 'editbugs@my.company',
'editbugs_user_passwd' => '******',
'editbugs_user_api_key' => 'zQ5ewBzq3gTrdBKYq9K1ZqJMjifKx3cKleE6k9TQ',
'canconfirm_user_login' => 'canconfirm@my.company',
'canconfirm_user_passwd' => '******',
'tweakparams_user_login' => 'tweakparams@my.company',
'tweakparams_user_login_truncated' => 'tweakparams@my',
'tweakparams_user_passwd' => '******',
'disabled_user_login' => 'disabled@my.company',
'disabled_user_passwd' => '******',
'common_email' => '@my.company',
'test_extensions' => 0,
};
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
package Bugzilla::Extension::QA;
use 5.10.1;
use strict;
use warnings;
use constant NAME => 'QA';
use constant REQUIRED_MODULES => [
];
use constant OPTIONAL_MODULES => [
];
__PACKAGE__->NAME;
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
package Bugzilla::Extension::QA;
use 5.10.1;
use strict;
use warnings;
use base qw(Bugzilla::Extension);
use Bugzilla::Extension::QA::Util;
use Bugzilla::Constants;
use Bugzilla::Error;
use Bugzilla::Util;
use Bugzilla::Bug;
use Bugzilla::User;
our $VERSION = '1.0';
sub page_before_template {
my ($self, $args) = @_;
return if $args->{page_id} ne 'qa/email_in.html';
my $template = Bugzilla->template;
my $cgi = Bugzilla->cgi;
print $cgi->header;
# Needed to make sure he can access and edit bugs.
my $user = Bugzilla::User->check($cgi->param('sender'));
Bugzilla->set_user($user);
my ($output, $tmpl_file);
my $action = $cgi->param('action') || '';
my $vars = { sender => $user, action => $action, pid => $$ };
if ($action eq 'create') {
$tmpl_file = 'qa/create_bug.txt.tmpl';
}
elsif ($action eq 'create_with_headers') {
$tmpl_file = 'qa/create_bug_with_headers.txt.tmpl';
}
elsif ($action =~ /^update(_with_headers)?$/) {
my $f = $1 || '';
$tmpl_file = "qa/update_bug$f.txt.tmpl";
my $bug = Bugzilla::Bug->check($cgi->param('bug_id'));
$vars->{bug_id} = $bug->id;
}
else {
ThrowUserError('unknown_action', { action => $action });
}
$template->process($tmpl_file, $vars, \$output)
or ThrowTemplateError($template->error());
my $file = "/tmp/email_in_$$.txt";
open(FH, '>', $file);
print FH $output;
close FH;
$output = `email_in.pl -v < $file 2>&1`;
unlink $file;
parse_output($output, $vars);
$template->process('qa/results.html.tmpl', $vars)
or ThrowTemplateError($template->error());
}
__PACKAGE__->NAME;
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
package Bugzilla::Extension::QA::Util;
use 5.10.1;
use strict;
use warnings;
use base qw(Exporter);
our @EXPORT = qw(
parse_output
);
sub parse_output {
my ($output, $vars) = @_;
$vars->{error} = ($output =~ /software error/i) ? 1 : 0;
$vars->{output} = $output;
$vars->{bug_id} ||= ($output =~ /Created bug (\d+)/i) ? $1 : undef;
}
1;
Template hooks go in this directory. Template hooks are called in normal
Bugzilla templates like [% Hook.process('some-hook') %].
More information about them can be found in the documentation of
Bugzilla::Extension. (Do "perldoc Bugzilla::Extension" from the main
Bugzilla directory to see that documentation.)
[%# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
#%]
Normal templates go in this directory. You can load them in your
code like this:
use Bugzilla::Error;
my $template = Bugzilla->template;
$template->process('qa/some-template.html.tmpl')
or ThrowTemplateError($template->error());
That would be how to load a file called some-template.html.tmpl that
was in this directory.
Note that you have to be careful that the full path of your template
never conflicts with a template that exists in Bugzilla or in
another extension, or your template might override that template. That's why
we created this directory called 'qa' for you, so you
can put your templates in here to help avoid conflicts.
[%# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
#%]
From: [% sender.email %]
Subject: [% terms.Bug %] created using email_in.pl
Content-Type: text/plain; charset="UTF-8"
@product = TestProduct
@component = TestComponent
@version = unspecified
This [% terms.bug %] has been created using email_in.pl (PID: [% pid %]).
[%# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
#%]
From - Sat Jan 1 18:38:17 2011
X-Account-Key: account2
X-UIDL: GmailId12d42784d83cb4a4
X-Mozilla-Status: 0011
X-Mozilla-Status2: 00000000
X-Mozilla-Keys:
Return-Path: <foo@bar.com>
Received: from [192.168.0.2] (provider.com [51.162.153.14])
by mx.google.com with ESMTPS id m10sm12712256wbc.4.2011.01.01.09.38.01
(version=TLSv1/SSLv3 cipher=RC4-MD5);
Sat, 01 Jan 2011 09:38:01 -0800 (PST)
Message-ID: <4D1F6580.9060076@gmail.com>
Date: Sat, 01 Jan 2011 18:38:08 +0100
User-Agent: Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.9.2.13) Gecko/20101207 Lightning/1.0b2 Thunderbird/3.1.7
MIME-Version: 1.0
From: [% sender.email %]
Subject: [% terms.Bug %] created using email_in.pl (with email headers)
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: 8bit
@product = TestProduct
@component = TestComponent
@version = unspecified
This [% terms.bug %] has been created using email_in.pl (PID: [% pid %]) with email headers.
[%# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
#%]
[% title = BLOCK %]
[% IF error %]
Unexpected error
[% ELSE %]
email_in.pl output
[% END %]
[% END %]
[% PROCESS global/header.html.tmpl %]
<h1>Action '[% action FILTER html %]' successful</h1>
<div>
<p>PID: <span id="pid">[% pid FILTER html %]</span></p>
<p>[%+ terms.Bug %] ID: <span id="bug_id">[% bug_id FILTER html %]</span></p>
<p>Full output:</p>
<pre id="output">[% output FILTER html_light %]</pre>
[% PROCESS global/footer.html.tmpl %]
[%# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
#%]
From: [% sender.email %]
Subject: [[% terms.Bug %] [%+ bug_id %]] This subject is ignored, only the [% terms.bug %] ID matters
Content-Type: text/plain; charset="UTF-8"
Comment added by email_in.pl (PID: [% pid %]). No other changes.
[%# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
#%]
From - Sat Jan 1 18:38:17 2011
X-Account-Key: account2
X-UIDL: GmailId12d42784d83cb4a4
X-Mozilla-Status: 0011
X-Mozilla-Status2: 00000000
X-Mozilla-Keys:
Return-Path: <foo@bar.com>
Received: from [192.168.0.2] (provider.com [51.162.153.14])
by mx.google.com with ESMTPS id m10sm12712256wbc.4.2011.01.01.09.38.01
(version=TLSv1/SSLv3 cipher=RC4-MD5);
Sat, 01 Jan 2011 09:38:01 -0800 (PST)
Message-ID: <4D1F6580.9060076@gmail.com>
Date: Sat, 01 Jan 2011 18:38:08 +0100
User-Agent: Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.9.2.13) Gecko/20101207 Lightning/1.0b2 Thunderbird/3.1.7
MIME-Version: 1.0
From: [% sender.email %]
Subject: [[% terms.Bug %] [%+ bug_id %]] This subject is ignored, only the [% terms.bug %] ID matters
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: 8bit
Comment added by email_in.pl (PID: [% pid %]) with email headers. No other changes.
Web-accessible files, like JavaScript, CSS, and images go in this
directory. You can reference them directly in your HTML. For example,
if you have a file called "style.css" and your extension is called
"Foo", you would put it in "extensions/Foo/web/style.css", and then
you could link to it in HTML like:
<link href="extensions/Foo/web/style.css" rel="stylesheet" type="text/css">
\ No newline at end of file
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
# This test combines two field/operator combinations using AND in
# a single boolean chart.
package Bugzilla::Test::Search::AndTest;
use parent qw(Bugzilla::Test::Search::OrTest);
use Bugzilla::Test::Search::Constants;
use List::MoreUtils qw(all);
use constant type => 'AND';
#############
# Accessors #
#############
# In an AND test, bugs ARE supposed to be contained only if they are contained
# by ALL tests.
sub bug_is_contained {
my ($self, $number) = @_;
return all { $_->bug_is_contained($number) } $self->field_tests;
}
sub _bug_will_actually_be_contained {
my ($self, $number) = @_;
return all { $_->will_actually_contain_bug($number) } $self->field_tests;
}
##############################
# Bugzilla::Search arguments #
##############################
sub search_params {
my ($self) = @_;
my @all_params = map { $_->search_params } $self->field_tests;
my %params;
my $chart = 0;
foreach my $item (@all_params) {
$params{"field0-$chart-0"} = $item->{'field0-0-0'};
$params{"type0-$chart-0"} = $item->{'type0-0-0'};
$params{"value0-$chart-0"} = $item->{'value0-0-0'};
$chart++;
}
return \%params;
}
1;
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
# This module represents a test with custom URL parameters.
# Tests like this are specified in CUSTOM_SEARCH_TESTS in
# Bugzilla::Test::Search::Constants.
package Bugzilla::Test::Search::CustomTest;
use parent qw(Bugzilla::Test::Search::FieldTest);
use strict;
use warnings;
use Bugzilla::Test::Search::FieldTest;
use Bugzilla::Test::Search::OperatorTest;
use Storable qw(dclone);
###############
# Constructor #
###############
sub new {
my ($class, $test, $search_test) = @_;
bless { raw_test => dclone($test), search_test => $search_test }, $class;
}
#############
# Accessors #
#############
sub search_test { return $_[0]->{search_test} }
sub name { return 'Custom: ' . $_[0]->test->{name} }
sub test { return $_[0]->{raw_test} }
sub operator_test { die "unimplemented" }
sub field_object { die "unimplemented" }
sub main_value { die "unimplenmented" }
sub test_value { die "unimplemented" }
# Custom tests don't use transforms.
sub transformed_value_was_equal { 0 }
sub debug_value {
my ($self) = @_;
my $string = '';
my $params = $self->search_params;
foreach my $param (keys %$params) {
$string .= $param . "=" . $params->{$param} . '&';
}
chop($string);
return $string;
}
# The tests we know are broken for this operator/field combination.
sub _known_broken { return {} }
sub contains_known_broken { return undef }
sub search_known_broken { return undef }
sub field_not_yet_implemented { return undef }
sub invalid_field_operator_combination { return undef }
#########################################
# Accessors: Bugzilla::Search Arguments #
#########################################
# Converts the f, o, v rows into f0, o0, v0, etc. and translates
# the values appropriately.
sub search_params {
my ($self) = @_;
my %params = %{ $self->test->{top_params} || {} };
my $counter = 0;
foreach my $row (@{ $self->test->{params} }) {
$row->{v} = $self->translate_value($row) if exists $row->{v};
foreach my $key (keys %$row) {
$params{"${key}$counter"} = $row->{$key};
}
$counter++;
}
return \%params;
}
sub translate_value {
my ($self, $row) = @_;
my $as_test = { field => $row->{f}, operator => $row->{o},
value => $row->{v} };
my $operator_test = new Bugzilla::Test::Search::OperatorTest($row->{o},
$self->search_test);
my $field = Bugzilla::Field->check($row->{f});
my $field_test = new Bugzilla::Test::Search::FieldTest($operator_test,
$field, $as_test);
return $field_test->translated_value;
}
sub search_columns {
my ($self) = @_;
return ['bug_id', @{ $self->test->{columns} || [] }];
}
1;
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
# This is the same as a FieldTest, except that it uses normal URL
# parameters instead of Boolean Charts.
package Bugzilla::Test::Search::FieldTestNormal;
use strict;
use warnings;
use parent qw(Bugzilla::Test::Search::FieldTest);
use Scalar::Util qw(blessed);
use constant CH_OPERATOR => {
changedafter => 'chfieldfrom',
changedbefore => 'chfieldto',
changedto => 'chfieldvalue',
};
use constant EMAIL_FIELDS => qw(assigned_to qa_contact cc reporter commenter);
# Normally, we just clone a FieldTest because that's the best for performance,
# overall--that way we don't have to translate the value again. However,
# sometimes (like in Bugzilla::Test::Search's direct code) we just want
# to create a FieldTestNormal.
sub new {
my $class = shift;
my ($first_arg) = @_;
if (blessed $first_arg
and $first_arg->isa('Bugzilla::Test::Search::FieldTest'))
{
my $self = { %$first_arg };
return bless $self, $class;
}
return $class->SUPER::new(@_);
}
sub name {
my $self = shift;
my $name = $self->SUPER::name(@_);
return "$name (Normal Params)";
}
sub search_columns {
my $self = shift;
my $field = $self->field;
# For the assigned_to, qa_contact, and reporter fields, have the
# "Normal Params" test check that the _realname columns work
# all by themselves.
if (grep($_ eq $field, EMAIL_FIELDS) && $self->field_object->buglist) {
return ['bug_id', "${field}_realname"]
}
return $self->SUPER::search_columns(@_);
}
sub search_params {
my ($self) = @_;
my $field = $self->field;
my $operator = $self->operator;
my $value = $self->translated_value;
if ($operator eq 'anyexact') {
$value = [split ',', $value];
}
if (my $ch_param = CH_OPERATOR->{$operator}) {
if ($field eq 'creation_ts') {
$field = '[Bug creation]';
}
return { chfield => $field, $ch_param => $value };
}
if ($field eq 'delta_ts' and $operator eq 'greaterthaneq') {
return { chfieldfrom => $value };
}
if ($field eq 'delta_ts' and $operator eq 'lessthaneq') {
return { chfieldto => $value };
}
if ($field eq 'deadline' and $operator eq 'greaterthaneq') {
return { deadlinefrom => $value };
}
if ($field eq 'deadline' and $operator eq 'lessthaneq') {
return { deadlineto => $value };
}
if (grep { $_ eq $field } EMAIL_FIELDS) {
$field = 'longdesc' if $field eq 'commenter';
return {
email1 => $value,
"email${field}1" => 1,
emailtype1 => $operator,
# Used to do extra tests on special sorts of email* combinations.
%{ $self->test->{extra_params} || {} },
};
}
$field =~ s/\./_/g;
return { $field => $value, "${field}_type" => $operator };
}
1;
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
# This module represents the SQL Injection tests that get run on a single
# operator/field combination for Bugzilla::Test::Search.
package Bugzilla::Test::Search::InjectionTest;
use parent qw(Bugzilla::Test::Search::FieldTest);
use strict;
use warnings;
use Bugzilla::Test::Search::Constants;
use Test::Exception;
sub num_tests { return NUM_SEARCH_TESTS }
sub _known_broken {
my ($self) = @_;
my $operator_broken = INJECTION_BROKEN_OPERATOR->{$self->operator};
# We don't want to auto-vivify $operator_broken and thus make it true.
my @field_ok = $operator_broken ? @{ $operator_broken->{field_ok} || [] }
: ();
$operator_broken = undef if grep { $_ eq $self->field } @field_ok;
my $field_broken = INJECTION_BROKEN_FIELD->{$self->field}
|| INJECTION_BROKEN_FIELD->{$self->field_object->type};
# We don't want to auto-vivify $field_broken and thus make it true.
my @operator_ok = $field_broken ? @{ $field_broken->{operator_ok} || [] }
: ();
$field_broken = undef if grep { $_ eq $self->operator } @operator_ok;
return $operator_broken || $field_broken || {};
}
sub sql_error_ok { return $_[0]->_known_broken->{sql_error} }
# Injection tests only skip fields on certain dbs.
sub field_not_yet_implemented {
my ($self) = @_;
# We use the constant directly because we don't want operator_ok
# or field_ok to stop us.
my $broken = INJECTION_BROKEN_FIELD->{$self->field}
|| INJECTION_BROKEN_FIELD->{$self->field_object->type};
my $skip_for_dbs = $broken->{db_skip};
return undef if !$skip_for_dbs;
my $dbh = Bugzilla->dbh;
if (my ($skip) = grep { $dbh->isa("Bugzilla::DB::$_") } @$skip_for_dbs) {
my $field = $self->field;
return "$field injection testing is not supported with $skip";
}
return undef;
}
# Injection tests don't do translation.
sub translated_value { $_[0]->test_value }
sub name { return "injection-" . $_[0]->SUPER::name; }
# Injection tests don't check content.
sub _test_content {}
sub _test_sql {
my $self = shift;
my ($sql) = @_;
my $dbh = Bugzilla->dbh;
my $name = $self->name;
if (my $error_ok = $self->sql_error_ok) {
throws_ok { $dbh->selectall_arrayref($sql) } $error_ok,
"$name: SQL query dies, as we expect";
return;
}
return $self->SUPER::_test_sql(@_);
}
1;
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
# This module runs tests just like a normal FieldTest, AndTest,
# or OrTest, but in a NOT chart instead of a normal chart.
#
# Logically this should be a mixin of some sort so that we can apply
# it to OrTest and AndTest, but without Moose there isn't much of an
# easy way to do that.
package Bugzilla::Test::Search::NotTest;
use parent qw(Bugzilla::Test::Search::FieldTest);
use strict;
use warnings;
use Bugzilla::Test::Search::Constants;
# We just clone a FieldTest because that's the best for performance,
# overall--that way we don't have to translate the value again.
sub new {
my ($class, $field_test) = @_;
my $self = { %$field_test };
return bless $self, $class;
}
#############
# Accessors #
#############
sub name {
my ($self) = @_;
return "NOT(" . $self->SUPER::name . ")";
}
# True if this test is supposed to contain the numbered bug. Reversed for
# NOT tests.
sub bug_is_contained {
my $self = shift;
my ($number) = @_;
# No search ever returns bug 6, because it's protected by security groups
# that the searcher isn't a member of.
return 0 if $number == 6;
return $self->SUPER::bug_is_contained(@_) ? 0 : 1;
}
# NOT tests have their own constant for tracking broken-ness.
sub _known_broken {
my ($self) = @_;
return $self->SUPER::_known_broken(BROKEN_NOT, 'skip pg check');
}
sub search_params {
my ($self) = @_;
my %params = %{ $self->SUPER::search_params() };
$params{negate0} = 1;
return \%params;
}
1;
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
# This module represents the tests that get run on a single operator
# from the TESTS constant in Bugzilla::Search::Test::Constants.
package Bugzilla::Test::Search::OperatorTest;
use strict;
use warnings;
use Bugzilla::Test::Search::Constants;
use Bugzilla::Test::Search::FieldTest;
use Bugzilla::Test::Search::FieldTestNormal;
use Bugzilla::Test::Search::InjectionTest;
use Bugzilla::Test::Search::OrTest;
use Bugzilla::Test::Search::AndTest;
use Bugzilla::Test::Search::NotTest;
###############
# Constructor #
###############
sub new {
my ($invocant, $operator, $search_test) = @_;
$search_test ||= $invocant->search_test;
my $class = ref($invocant) || $invocant;
return bless { search_test => $search_test, operator => $operator }, $class;
}
#############
# Accessors #
#############
# The Bugzilla::Test::Search object that this is a child of.
sub search_test { return $_[0]->{search_test} }
# The operator being tested
sub operator { return $_[0]->{operator} }
# The tests that we're going to run on this operator.
sub tests { return @{ TESTS->{$_[0]->operator } } }
# The fields we're going to test for this operator.
sub test_fields { return $_[0]->search_test->all_fields }
sub run {
my ($self) = @_;
foreach my $field ($self->test_fields) {
foreach my $test ($self->tests) {
my $field_test =
new Bugzilla::Test::Search::FieldTest($self, $field, $test);
$field_test->run();
my $normal_test =
new Bugzilla::Test::Search::FieldTestNormal($field_test);
$normal_test->run();
my $not_test = new Bugzilla::Test::Search::NotTest($field_test);
$not_test->run();
next if !$self->search_test->option('long');
# Run the OR tests. This tests every other operator (including
# this operator itself) in combination with every other field,
# in an OR with this operator and field.
foreach my $other_operator ($self->search_test->all_operators) {
$self->run_join_tests($field_test, $other_operator);
}
}
foreach my $test (INJECTION_TESTS) {
my $injection_test =
new Bugzilla::Test::Search::InjectionTest($self, $field, $test);
$injection_test->run();
}
}
}
sub run_join_tests {
my ($self, $field_test, $other_operator) = @_;
my $other_operator_test = $self->new($other_operator);
foreach my $other_test ($other_operator_test->tests) {
foreach my $other_field ($self->test_fields) {
$self->_run_one_join_test($field_test, $other_operator_test,
$other_field, $other_test);
$self->search_test->clean_test_history();
}
}
}
sub _run_one_join_test {
my ($self, $field_test, $other_operator_test, $other_field, $other_test) = @_;
my $other_field_test =
new Bugzilla::Test::Search::FieldTest($other_operator_test,
$other_field, $other_test);
my $or_test = new Bugzilla::Test::Search::OrTest($field_test,
$other_field_test);
$or_test->run();
my $and_test = new Bugzilla::Test::Search::AndTest($field_test,
$other_field_test);
$and_test->run();
}
1;
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
# This test combines two field/operator combinations using OR in
# a single boolean chart.
package Bugzilla::Test::Search::OrTest;
use parent qw(Bugzilla::Test::Search::FieldTest);
use Bugzilla::Test::Search::Constants;
use List::MoreUtils qw(all any uniq);
use constant type => 'OR';
###############
# Constructor #
###############
sub new {
my $class = shift;
my $self = { field_tests => [@_] };
return bless $self, $class;
}
#############
# Accessors #
#############
sub field_tests { return @{ $_[0]->{field_tests} } }
sub search_test { ($_[0]->field_tests)[0]->search_test }
sub name {
my ($self) = @_;
my @names = map { $_->name } $self->field_tests;
return join('-' . $self->type . '-', @names);
}
# In an OR test, bugs ARE supposed to be contained if they are contained
# by ANY test.
sub bug_is_contained {
my ($self, $number) = @_;
return any { $_->bug_is_contained($number) } $self->field_tests;
}
# Needed only for failure messages
sub debug_value {
my ($self) = @_;
my @values = map { $_->field . ' ' . $_->debug_value } $self->field_tests;
return join(' ' . $self->type . ' ', @values);
}
########################
# SKIP & TODO Messages #
########################
sub field_not_yet_implemented {
my ($self) = @_;
return $self->_join_messages('field_not_yet_implemented');
}
sub invalid_field_operator_combination {
my ($self) = @_;
return $self->_join_messages('invalid_field_operator_combination');
}
sub search_known_broken {
my ($self) = @_;
return $self->_join_messages('search_known_broken');
}
sub _join_messages {
my ($self, $message_method) = @_;
my @messages = map { $_->$message_method } $self->field_tests;
@messages = grep { $_ } @messages;
return join(' AND ', @messages);
}
sub _bug_will_actually_be_contained {
my ($self, $number) = @_;
foreach my $test ($self->field_tests) {
# Some tests are broken in such a way that they actually
# generate no criteria in the SQL. In this case, the only way
# the test contains the bug is if *another* test contains it.
next if $test->_known_broken->{no_criteria};
return 1 if $test->will_actually_contain_bug($number);
}
return 0;
}
sub contains_known_broken {
my ($self, $number) = @_;
if ( ( $self->bug_is_contained($number)
and !$self->_bug_will_actually_be_contained($number) )
or ( !$self->bug_is_contained($number)
and $self->_bug_will_actually_be_contained($number) ) )
{
my @messages = map { $_->contains_known_broken($number) }
$self->field_tests;
@messages = grep { $_ } @messages;
# Sometimes, with things that break because of no_criteria, there won't
# be anything in @messages even though we need to print out a message.
if (!@messages) {
my @no_criteria = grep { $_->_known_broken->{no_criteria} }
$self->field_tests;
@messages = map { "No criteria generated by " . $_->name }
@no_criteria;
}
die "broken test with no message" if !@messages;
return join(' AND ', @messages);
}
return undef;
}
##############################
# Bugzilla::Search arguments #
##############################
sub search_columns {
my ($self) = @_;
my @columns = map { @{ $_->search_columns } } $self->field_tests;
return [uniq @columns];
}
sub search_params {
my ($self) = @_;
my @all_params = map { $_->search_params } $self->field_tests;
my %params;
my $chart = 0;
foreach my $item (@all_params) {
$params{"field0-0-$chart"} = $item->{'field0-0-0'};
$params{"type0-0-$chart"} = $item->{'type0-0-0'};
$params{"value0-0-$chart"} = $item->{'value0-0-0'};
$chart++;
}
return \%params;
}
1;
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
package QA::REST;
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../../lib", "$RealBin/../../../local/lib/perl5";
use autodie;
use LWP::UserAgent;
use JSON;
use QA::Util;
use parent qw(LWP::UserAgent Exporter);
@QA::REST::EXPORT = qw(
MUST_FAIL
get_rest_client
);
use constant MUST_FAIL => 1;
sub get_rest_client {
my $rest_client = LWP::UserAgent->new( ssl_opts => { verify_hostname => 0 } );
bless($rest_client, 'QA::REST');
my $config = $rest_client->{bz_config} = get_config();
$rest_client->{bz_url} = $config->{browser_url} . '/' . $config->{bugzilla_installation} . '/rest/';
$rest_client->{bz_default_headers} = {'Accept' => 'application/json', 'Content-Type' => 'application/json'};
return $rest_client;
}
sub bz_config { return $_[0]->{bz_config}; }
sub call {
my ($self, $method, $data, $http_verb, $expect_to_fail) = @_;
$http_verb = lc($http_verb || 'GET');
$data //= {};
my %args = %{ $self->{bz_default_headers} };
# We do not pass the API key in the URL, so that it's not logged by the web server.
if ($http_verb eq 'get' && $data->{api_key}) {
$args{'X-BUGZILLA-API-KEY'} = $data->{api_key};
}
elsif ($http_verb ne 'get') {
$args{Content} = encode_json($data);
}
my $response = $self->$http_verb($self->{bz_url} . $method, %args);
my $res = decode_json($response->decoded_content);
if ($response->is_success xor $expect_to_fail) {
return $res;
}
else {
die 'error ' . $res->{code} . ': ' . $res->{message} . "\n";
}
}
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
# -*- Mode: perl; indent-tabs-mode: nil -*-
package QA::RPC;
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../../lib", "$RealBin/../../../local/lib/perl5";
use Data::Dumper;
use QA::Util;
use QA::Tests qw(PRIVATE_BUG_USER create_bug_fields);
use Storable qw(dclone);
use Test::More;
sub bz_config {
my $self = shift;
$self->{bz_config} ||= QA::Util::get_config();
return $self->{bz_config};
}
# True if we're doing calls over GET instead of POST.
sub bz_get_mode { return 0 }
# When doing bz_log_in over GET, we can't actually call User.login,
# we just store credentials here and then pass them as Bugzilla_login
# and Bugzilla_password with every future call until User.logout is called
# (which actually just calls _bz_clear_credentials, under GET).
sub _bz_credentials {
my ($self, $user, $pass) = @_;
if (@_ == 3) {
$self->{_bz_credentials}->{user} = $user;
$self->{_bz_credentials}->{pass} = $pass;
}
return $self->{_bz_credentials};
}
sub _bz_clear_credentials { delete $_[0]->{_bz_credentials} }
################################
# Helpers for RPC test scripts #
################################
sub bz_log_in {
my ($self, $user) = @_;
my $username = $self->bz_config->{"${user}_user_login"};
my $password = $self->bz_config->{"${user}_user_passwd"};
if ($self->bz_get_mode) {
$self->_bz_credentials($username, $password);
return;
}
my $call = $self->bz_call_success(
'User.login', { login => $username, password => $password });
cmp_ok($call->result->{id}, 'gt', 0, $self->TYPE . ": Logged in as $user");
$self->{_bz_credentials}->{token} = $call->result->{token};
}
sub bz_call_success {
my ($self, $method, $orig_args, $test_name) = @_;
my $args = $orig_args ? dclone($orig_args) : {};
if ($self->bz_get_mode and $method eq 'User.logout') {
$self->_bz_clear_credentials();
return;
}
my $call;
# Under XMLRPC::Lite, if we pass undef as the second argument,
# it sends a single param <value />, which shows up as an
# empty string on the Bugzilla side.
if ($self->{_bz_credentials}->{token}) {
$args->{Bugzilla_token} = $self->{_bz_credentials}->{token};
}
if (scalar keys %$args) {
$call = $self->call($method, $args);
}
else {
$call = $self->call($method);
}
$test_name ||= "$method returned successfully";
$self->_handle_undef_response($test_name) if !$call;
ok(!$call->fault, $self->TYPE . ": $test_name")
or diag($call->faultstring);
if ($method eq 'User.logout') {
delete $self->{_bz_credentials}->{token};
}
return $call;
}
sub bz_call_fail {
my ($self, $method, $orig_args, $faultstring, $test_name) = @_;
my $args = $orig_args ? dclone($orig_args) : {};
if ($self->{_bz_credentials}->{token}) {
$args->{Bugzilla_token} = $self->{_bz_credentials}->{token};
}
$test_name ||= "$method failed (as intended)";
my $call = $self->call($method, $args);
$self->_handle_undef_response($test_name) if !$call;
ok($call->fault, $self->TYPE . ": $test_name")
or diag("Returned: " . Dumper($call->result));
if (defined $faultstring) {
cmp_ok(trim($call->faultstring), '=~', $faultstring,
$self->TYPE . ": Got correct fault for $method");
}
ok($call->faultcode
&& (($call->faultcode < 32000 && $call->faultcode > -32000)
# Fault codes 32610 and above are OK because they are errors
# that we expect and test for sometimes.
|| $call->faultcode >= 32610),
$self->TYPE . ': Fault code is set properly')
or diag("Code: " . $call->faultcode
. " Message: " . $call->faultstring);
return $call;
}
sub _handle_undef_response {
my ($self, $test_name) = @_;
my $response = $self->transport->http_response;
die "$test_name:\n", $response->as_string;
}
sub bz_get_products {
my ($self) = @_;
$self->bz_log_in('QA_Selenium_TEST');
my $accessible = $self->bz_call_success('Product.get_accessible_products');
my $prod_call = $self->bz_call_success('Product.get', $accessible->result);
my %products;
foreach my $prod (@{ $prod_call->result->{products} }) {
$products{$prod->{name}} = $prod->{id};
}
$self->bz_call_success('User.logout');
return \%products;
}
sub _string_array { map { random_string() } (1..$_[0]) }
sub bz_create_test_bugs {
my ($self, $second_private) = @_;
my $config = $self->bz_config;
my @whiteboard_strings = _string_array(3);
my @summary_strings = _string_array(3);
my $public_bug = create_bug_fields($config);
$public_bug->{whiteboard} = join(' ', @whiteboard_strings);
$public_bug->{summary} = join(' ', @summary_strings);
my $private_bug = dclone($public_bug);
if ($second_private) {
$private_bug->{product} = 'QA-Selenium-TEST';
$private_bug->{component} = 'QA-Selenium-TEST';
$private_bug->{target_milestone} = 'QAMilestone';
$private_bug->{version} = 'QAVersion';
# Although we don't directly use this, this helps some tests that
# depend on the values in $private_bug.
$private_bug->{creator} = $config->{PRIVATE_BUG_USER . '_user_login'};
}
my @create_bugs = (
{ user => 'editbugs',
args => $public_bug,
test => 'Create a public bug' },
{ user => $second_private ? PRIVATE_BUG_USER : 'editbugs',
args => $private_bug,
test => $second_private ? 'Create a private bug'
: 'Create a second public bug' },
);
my $post_success = sub {
my ($call, $t) = @_;
my $id = $call->result->{id};
$t->{args}->{id} = $id;
};
# Creating the bugs isn't really a test, it's just preliminary work
# for the tests. So we just run it with one of the RPC clients.
$self->bz_run_tests(tests => \@create_bugs, method => 'Bug.create',
post_success => $post_success);
return ($public_bug, $private_bug);
}
sub bz_run_tests {
my ($self, %params) = @_;
# Required params
my $config = $self->bz_config;
my $tests = $params{tests};
my $method = $params{method};
# Optional params
my $post_success = $params{post_success};
my $pre_call = $params{pre_call};
my $former_user = '';
foreach my $t (@$tests) {
# Only logout/login if the user has changed since the last test
# (this saves us LOTS of needless logins).
my $user = $t->{user} || '';
if ($former_user ne $user) {
$self->bz_call_success('User.logout') if $former_user;
$self->bz_log_in($user) if $user;
$former_user = $user;
}
$pre_call->($t, $self) if $pre_call;
if ($t->{error}) {
$self->bz_call_fail($method, $t->{args}, $t->{error}, $t->{test});
}
else {
my $call = $self->bz_call_success($method, $t->{args}, $t->{test});
if ($call->result && $post_success) {
$post_success->($call, $t, $self);
}
}
}
$self->bz_call_success('User.logout') if $former_user;
}
sub bz_test_bug {
my ($self, $fields, $bug, $expect, $t, $creation_time) = @_;
foreach my $field (sort @$fields) {
# "description" is used by Bug.create but comments are not returned
# by Bug.get or Bug.search.
next if $field eq 'description';
my @include = @{ $t->{args}->{include_fields} || [] };
my @exclude = @{ $t->{args}->{exclude_fields} || [] };
if ( (@include and !grep($_ eq $field, @include))
or (@exclude and grep($_ eq $field, @exclude)) )
{
ok(!exists $bug->{$field}, "$field is not included")
or diag Dumper($bug);
next;
}
if ($field =~ /^is_/) {
ok(defined $bug->{$field}, $self->TYPE . ": $field is not null");
is($bug->{$field} ? 1 : 0, $expect->{$field} ? 1 : 0,
$self->TYPE . ": $field has the right boolean value");
}
elsif ($field eq 'cc') {
foreach my $cc_item (@{ $expect->{cc} || [] }) {
ok(grep($_ eq $cc_item, @{ $bug->{cc} }),
$self->TYPE . ": $field contains $cc_item");
}
}
elsif ($field eq 'creation_time' or $field eq 'last_change_time') {
my $creation_day;
# XML-RPC and JSON-RPC have different date formats.
if ($self->isa('QA::RPC::XMLRPC')) {
$creation_day = $creation_time->ymd('');
}
else {
$creation_day = $creation_time->ymd;
}
like($bug->{$field}, qr/^\Q${creation_day}\ET\d\d:\d\d:\d\d/,
$self->TYPE . ": $field has the right format");
}
else {
is_deeply($bug->{$field}, $expect->{$field},
$self->TYPE . ": $field value is correct");
}
}
}
1;
__END__
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
# -*- Mode: perl; indent-tabs-mode: nil -*-
package QA::RPC::JSONRPC;
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../../../lib", "$RealBin/../../../../local/lib/perl5";
use QA::RPC;
BEGIN {
our @ISA = qw(QA::RPC);
if (eval { require JSON::RPC::Client }) {
push(@ISA, 'JSON::RPC::Client');
}
else {
require JSON::RPC::Legacy::Client;
push(@ISA, 'JSON::RPC::Legacy::Client');
}
}
use URI::Escape;
use constant DATETIME_REGEX => qr/^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\dZ$/;
sub TYPE {
my ($self) = @_;
return $self->bz_get_mode ? 'JSON-RPC GET' : 'JSON-RPC';
}
#################################
# Consistency with XMLRPC::Lite #
#################################
sub ua {
my $self = shift;
if ($self->{ua} and not $self->{ua}->isa('QA::RPC::UserAgent')) {
bless $self->{ua}, 'QA::RPC::UserAgent';
}
return $self->SUPER::ua(@_);
}
sub transport { $_[0]->ua }
sub bz_get_mode {
my ($self, $value) = @_;
$self->{bz_get_mode} = $value if @_ > 1;
return $self->{bz_get_mode};
}
sub _bz_callback {
my ($self, $value) = @_;
$self->{bz_callback} = $value if @_ > 1;
return $self->{bz_callback};
}
sub call {
my $self = shift;
my ($method, $args) = @_;
my %params = ( method => $method );
$params{params} = $args ? [$args] : [];
my $config = $self->bz_config;
my $url = $config->{browser_url} . "/"
. $config->{bugzilla_installation} . "/jsonrpc.cgi";
my $result;
if ($self->bz_get_mode) {
my $method_escaped = uri_escape($method);
$url .= "?method=$method_escaped";
if (my $cred = $self->_bz_credentials) {
$args->{Bugzilla_login} = $cred->{user}
if !exists $args->{Bugzilla_login};
$args->{Bugzilla_password} = $cred->{pass}
if !exists $args->{Bugzilla_password};
}
if ($args) {
my $params_json = $self->json->encode($args);
my $params_escaped = uri_escape($params_json);
$url .= "&params=$params_escaped";
}
if ($self->version eq '1.1') {
$url .= "&version=1.1";
}
my $callback = delete $args->{callback};
if (defined $callback) {
$self->_bz_callback($callback);
$url .= "&callback=" . uri_escape($callback);
}
$result = $self->SUPER::call($url);
}
else {
$result = $self->SUPER::call($url, \%params);
}
if ($result) {
bless $result, 'QA::RPC::JSONRPC::ReturnObject';
}
return $result;
}
sub _get {
my $self = shift;
my $result = $self->SUPER::_get(@_);
# Simple JSONP support for tests. We just remove the callback from
# the return value.
my $callback = $self->_bz_callback;
if (defined $callback and $result->is_success) {
my $content = $result->content;
$content =~ s/^(?:\/\*\*\/)?\Q$callback(\E(.*)\)$/$1/s;
$result->content($content);
# We don't need this anymore, and we don't want it to affect
# future calls.
delete $self->{bz_callback};
}
return $result;
}
1;
package QA::RPC::JSONRPC::ReturnObject;
use strict;
BEGIN {
if (eval { require JSON::RPC::Client }) {
our @ISA = qw(JSON::RPC::ReturnObject);
}
else {
require JSON::RPC::Legacy::Client;
our @ISA = qw(JSON::RPC::Legacy::ReturnObject);
}
}
#################################
# Consistency with XMLRPC::Lite #
#################################
sub faultstring { $_[0]->{content}->{error}->{message} }
sub faultcode { $_[0]->{content}->{error}->{code} }
sub fault { $_[0]->is_error }
1;
package QA::RPC::UserAgent;
use strict;
use base qw(LWP::UserAgent);
########################################
# Consistency with XMLRPC::Lite's ->ua #
########################################
sub send_request {
my $self = shift;
my $response = $self->SUPER::send_request(@_);
$self->http_response($response);
# JSON::RPC::Client can't handle 500 responses, even though
# they're required by the JSON-RPC spec.
$response->code(200);
return $response;
}
# Copied directly from SOAP::Lite::Transport::HTTP.
sub http_response {
my $self = shift;
if (@_) { $self->{'_http_response'} = shift; return $self }
return $self->{'_http_response'};
}
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
# -*- Mode: perl; indent-tabs-mode: nil -*-
package QA::RPC::XMLRPC;
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../../../lib", "$RealBin/../../../../local/lib/perl5";
use base qw(QA::RPC XMLRPC::Lite);
use constant TYPE => 'XML-RPC';
use constant DATETIME_REGEX => qr/^\d{8}T\d\d:\d\d:\d\d$/;
1;
__END__
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
# -*- Mode: perl; indent-tabs-mode: nil -*-
package QA::Tests;
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../../lib", "$RealBin/../../../local/lib/perl5";
use base qw(Exporter);
our @EXPORT_OK = qw(
PRIVATE_BUG_USER
STANDARD_BUG_TESTS
bug_tests
create_bug_fields
);
use constant INVALID_BUG_ID => -1;
use constant INVALID_BUG_ALIAS => 'aaaaaaa12345';
use constant PRIVATE_BUG_USER => 'QA_Selenium_TEST';
use constant CREATE_BUG => {
'priority' => 'Highest',
'status' => 'CONFIRMED',
'version' => 'unspecified',
'creator' => 'editbugs',
'description' => '-- Comment Created By Bugzilla XML-RPC Tests --',
'cc' => ['unprivileged'],
'component' => 'c1',
'platform' => 'PC',
# It's necessary to assign the bug to somebody who isn't in the
# timetracking group, for the Bug.update tests.
'assigned_to' => PRIVATE_BUG_USER,
'summary' => 'WebService Test Bug',
'product' => 'Another Product',
'op_sys' => 'Linux',
'severity' => 'normal',
'qa_contact' => 'canconfirm',
version => 'Another1',
url => 'http://www.bugzilla.org/',
target_milestone => 'AnotherMS1',
};
sub create_bug_fields {
my ($config) = @_;
my %bug = %{ CREATE_BUG() };
foreach my $field (qw(creator assigned_to qa_contact)) {
my $value = $bug{$field};
$bug{$field} = $config->{"${value}_user_login"};
}
$bug{cc} = [map { $config->{$_ . "_user_login"} } @{ $bug{cc} }];
return \%bug;
}
sub bug_tests {
my ($public_id, $private_id) = @_;
return [
{ args => { ids => [$private_id] },
error => "You are not authorized to access",
test => 'Logged-out user cannot access a private bug',
},
{ args => { ids => [$public_id] },
test => 'Logged-out user can access a public bug.',
},
{ args => { ids => [INVALID_BUG_ID] },
error => "not a valid bug number",
test => 'Passing invalid bug id returns error "Invalid Bug ID"',
},
{ args => { ids => [undef] },
error => "You must enter a valid bug number",
test => 'Passing undef as bug id param returns error "Invalid Bug ID"',
},
{ args => { ids => [INVALID_BUG_ALIAS] },
error => "nor an alias to a bug",
test => 'Passing invalid bug alias returns error "Invalid Bug Alias"',
},
{ user => 'editbugs',
args => { ids => [$private_id] },
error => "You are not authorized to access",
test => 'Access to a private bug is denied to a user without privs',
},
{ user => 'unprivileged',
args => { ids => [$public_id] },
test => 'User without privs can access a public bug',
},
{ user => 'admin',
args => { ids => [$public_id] },
test => 'Admin can access a public bug.',
},
{ user => PRIVATE_BUG_USER,
args => { ids => [$private_id] },
test => 'User with privs can successfully access a private bug',
},
# This helps webservice_bug_attachment get private attachment ids
# from the public bug, and doesn't hurt for the other tests.
{ user => PRIVATE_BUG_USER,
args => { ids => [$public_id] },
test => 'User with privs can also access the public bug',
},
];
}
use constant STANDARD_BUG_TESTS => bug_tests('public_bug', 'private_bug');
1;
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
#######################################
# Tests for REST calls in Bugzilla.pm #
#######################################
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More tests => 11;
use QA::REST;
my $rest = get_rest_client();
my $config = $rest->bz_config;
my $version = $rest->call('version')->{version};
ok($version, "GET /rest/version returns $version");
my $extensions = $rest->call('extensions')->{extensions};
isa_ok($extensions, 'HASH', 'GET /rest/extensions');
my @ext_names = sort keys %$extensions;
# There is always at least the QA extension enabled.
ok(scalar(@ext_names), scalar(@ext_names) . ' extension(s) found: ' . join(', ', @ext_names));
ok($extensions->{QA}, 'The QA extension is enabled, with version ' . $extensions->{QA}->{version});
my $timezone = $rest->call('timezone')->{timezone};
ok($timezone, "GET /rest/timezone retuns $timezone");
my $time = $rest->call('time');
foreach my $type (qw(db_time web_time)) {
ok($time->{$type}, "GET /rest/time returns $type = " . $time->{$type});
}
# Logged-out users can only access the maintainer and requirelogin parameters.
my $params = $rest->call('parameters')->{parameters};
my @param_names = sort keys %$params;
ok(@param_names == 2 && defined $params->{maintainer} && defined $params->{requirelogin},
'Only 2 parameters accessible to logged-out users: ' . join(', ', @param_names));
# Powerless users can access much more parameters.
$params = $rest->call('parameters', { api_key => $config->{unprivileged_user_api_key} })->{parameters};
@param_names = sort keys %$params;
ok(@param_names > 2, scalar(@param_names) . ' parameters accessible to powerless users');
# Admins can access all parameters.
$params = $rest->call('parameters', { api_key => $config->{admin_user_api_key} })->{parameters};
@param_names = sort keys %$params;
ok(@param_names > 2, scalar(@param_names) . ' parameters accessible to admins');
my $timestamp = $rest->call('last_audit_time')->{last_audit_time};
ok($timestamp, "GET /rest/last_audit_time returns $timestamp");
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
#############################################
# Tests for REST calls in Classification.pm #
#############################################
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More tests => 7;
use QA::REST;
my $rest = get_rest_client();
my $config = $rest->bz_config;
my $args = { api_key => $config->{admin_user_api_key} };
my $params = $rest->call('parameters', $args)->{parameters};
my $use_class = $params->{useclassification};
ok(defined($use_class), 'Classifications are ' . ($use_class ? 'enabled' : 'disabled'));
# Admins can always access classifications, even when they are disabled.
my $class = $rest->call('classification/1', $args)->{classifications}->[0];
ok($class->{id}, "Admin found classification '" . $class->{name} . "' with the description '" . $class->{description} . "'");
my @products = sort map { $_->{name} } @{ $class->{products} };
ok(scalar(@products), scalar(@products) . ' product(s) found: ' . join(', ', @products));
$class = $rest->call('classification/Class2_QA', $args)->{classifications}->[0];
ok($class->{id}, "Admin found classification '" . $class->{name} . "' with the description '" . $class->{description} . "'");
@products = sort map { $_->{name} } @{ $class->{products} };
ok(scalar(@products), scalar(@products) . ' product(s) found: ' . join(', ', @products));
if ($use_class) {
# When classifications are enabled, everybody can query classifications...
# ... including logged-out users.
$class = $rest->call('classification/1')->{classifications}->[0];
ok($class->{id}, 'Logged-out users can access classification ' . $class->{name});
# ... and non-admins.
$class = $rest->call('classification/1', { api_key => $config->{editbugs_user_api_key} })->{classifications}->[0];
ok($class->{id}, 'Non-admins can access classification ' . $class->{name});
}
else {
# When classifications are disabled, only users in the 'editclassifications'
# group can access this method...
# ... logged-out users get an error.
my $error = $rest->call('classification/1', undef, undef, MUST_FAIL);
ok($error->{error} && $error->{code} == 900,
'Logged-out users cannot query classifications when disabled: ' . $error->{message});
# ... as well as non-admins.
$error = $rest->call('classification/1', { api_key => $config->{editbugs_user_api_key} }, undef, MUST_FAIL);
ok($error->{error} && $error->{code} == 900,
'Non-admins cannot query classifications when disabled: ' . $error->{message});
}
#!/usr/bin/perl -w
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
# For a description of this test, see Bugzilla::Test::Search
# in xt/lib/.
use strict;
use warnings;
use lib qw(. xt/lib lib local/lib/perl5);
use Bugzilla;
use Bugzilla::Constants;
use Bugzilla::Test::Search;
use Getopt::Long;
use Pod::Usage;
use Test::More;
my %switches;
GetOptions(\%switches, 'operators=s', 'top-operators=s', 'long',
'add-custom-fields', 'help|h') || die $@;
pod2usage(verbose => 1) if $switches{'help'};
plan skip_all => "BZ_WRITE_TESTS environment variable not set"
if !$ENV{BZ_WRITE_TESTS};
Bugzilla->usage_mode(USAGE_MODE_TEST);
my $test = new Bugzilla::Test::Search(\%switches);
plan tests => $test->num_tests;
$test->run();
__END__
=head1 NAME
search.t - Test L<Bugzilla::Search>
=head1 DESCRIPTION
This test tests L<Bugzilla::Search>.
Note that users may be prevented from writing new bugs, products, components,
etc. to your database while this test is running.
=head1 OPTIONS
=over
=item --long
Run AND and OR tests in addition to normal tests. Specifying
--long without also specifying L</--top-operators> is likely to
run your system out of memory.
=item --add-custom-fields
This adds every type of custom field to the database, so that they can
all be tested. Note that this B<CANNOT BE REVERSED>, so do not use this
switch on a production installation.
=item --operators=a,b,c
Limit the test to testing only the listed operators.
=item --top-operators=a,b,c
Limit the top-level tested operators to the following list. This
means that for normal tests, only the listed operators will be tested.
However, for OR and AND tests, all other operators will be tested
along with the operators you listed.
=item --help
Display this help.
=back
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium();
log_in($sel, $config, 'admin');
set_parameters($sel, { "Bug Change Policies" => {"letsubmitterchoosepriority-off" => undef} });
file_bug_in_product($sel, "TestProduct");
ok(!$sel->is_text_present("Priority"), "The Priority label is not present");
ok(!$sel->is_element_present("//select[\@name='priority']"), "The Priority drop-down menu is not present");
set_parameters($sel, { "Bug Change Policies" => {"letsubmitterchoosepriority-on" => undef} });
file_bug_in_product($sel, "TestProduct");
$sel->is_text_present_ok("Priority");
$sel->is_element_present_ok("//select[\@name='priority']");
logout($sel);
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium();
# Enable classifications
log_in($sel, $config, 'admin');
set_parameters($sel, { "Bug Fields" => {"useclassification-on" => undef} });
# Create a new classification.
go_to_admin($sel);
$sel->click_ok("link=Classifications");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Select classification");
# Delete old classifications if this script failed.
# Accessing action=delete directly must 1) trigger the security check page,
# and 2) automatically reclassify products in this classification.
if ($sel->is_text_present("cone")) {
$sel->open_ok("/$config->{bugzilla_installation}/editclassifications.cgi?action=delete&amp;classification=cone");
$sel->title_is("Suspicious Action");
$sel->click_ok("confirm");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Classification Deleted");
}
if ($sel->is_text_present("ctwo")) {
$sel->open_ok("/$config->{bugzilla_installation}/editclassifications.cgi?action=delete&amp;classification=ctwo");
$sel->title_is("Suspicious Action");
$sel->click_ok("confirm");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Classification Deleted");
}
$sel->click_ok("link=Add a new classification");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Add new classification");
$sel->type_ok("classification", "cone");
$sel->type_ok("description", "Classification number 1");
$sel->click_ok('//input[@type="submit" and @value="Add"]');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("New Classification Created");
# Add TestProduct to the new classification. There should be no other
# products in this classification.
$sel->select_ok("prodlist", "value=TestProduct");
$sel->click_ok("add_products");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Reclassify products");
my @products = $sel->get_select_options("myprodlist");
ok(scalar @products == 1 && $products[0] eq 'TestProduct', "TestProduct successfully added to 'cone'");
# Create a new bug in this product/classification.
file_bug_in_product($sel, 'TestProduct', 'cone');
my $bug_summary = "Bug in classification cone";
$sel->type_ok("short_desc", $bug_summary);
$sel->type_ok("comment", "Created by Selenium with classifications turned on");
create_bug($sel, $bug_summary);
# Rename 'cone' to 'Unclassified', which must be rejected as it already exists,
# then to 'ctwo', which is not yet in use. Should work fine, even with products
# already in it.
go_to_admin($sel);
$sel->click_ok("link=Classifications");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Select classification");
$sel->click_ok("link=cone");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Edit classification");
$sel->type_ok("classification", "Unclassified");
$sel->click_ok("//input[\@value='Update']");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Classification Already Exists");
$sel->go_back_ok();
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Edit classification");
$sel->type_ok("classification", "ctwo");
$sel->click_ok("//input[\@value='Update']");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Classification Updated");
# Now try to delete the 'ctwo' classification. It should fail as there are
# products in it.
go_to_admin($sel);
$sel->click_ok("link=Classifications");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Select classification");
$sel->click_ok('//a[@href="editclassifications.cgi?action=del&classification=ctwo"]');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Error");
my $error = trim($sel->get_text("error_msg"));
ok($error =~ /there are products for this classification/, "Reject classification deletion");
# Reclassify the product before deleting the classification.
$sel->go_back_ok();
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Select classification");
$sel->click_ok('//a[@href="editclassifications.cgi?action=reclassify&classification=ctwo"]');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Reclassify products");
$sel->add_selection_ok("myprodlist", "label=TestProduct");
$sel->click_ok("remove_products");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Reclassify products");
$sel->click_ok("link=edit");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Select classification");
$sel->click_ok('//a[@href="editclassifications.cgi?action=del&classification=ctwo"]');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Delete classification");
$sel->is_text_present_ok("Do you really want to delete this classification?");
$sel->click_ok("//input[\@value='Yes, delete']");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Classification Deleted");
# Disable classifications and make sure you cannot edit them anymore.
set_parameters($sel, { "Bug Fields" => {"useclassification-off" => undef} });
$sel->open_ok("/$config->{bugzilla_installation}/editclassifications.cgi");
$sel->title_is("Classification Not Enabled");
logout($sel);
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium();
# Turn on 'requirelogin' and log out.
log_in($sel, $config, 'admin');
set_parameters($sel, { "User Authentication" => {"requirelogin-on" => undef} });
logout($sel);
# Accessing config.cgi should display no sensitive data.
$sel->open_ok("/$config->{bugzilla_installation}/config.cgi", undef, "Go to config.cgi (JS format)");
$sel->is_text_present_ok("var status = [ ];");
$sel->is_text_present_ok("var status_open = [ ];");
$sel->is_text_present_ok("var status_closed = [ ];");
$sel->is_text_present_ok("var resolution = [ ];");
$sel->is_text_present_ok("var keyword = [ ];");
$sel->is_text_present_ok("var platform = [ ];");
$sel->is_text_present_ok("var severity = [ ];");
$sel->is_text_present_ok("var field = [\n];");
ok(!$sel->is_text_present("cf_"), "No custom field displayed");
ok(!$sel->is_text_present("component["), "No component displayed");
ok(!$sel->is_text_present("version["), "No version displayed");
ok(!$sel->is_text_present("target_milestone["), "No target milestone displayed");
# Turn on 'requirelogin' and log out.
log_in($sel, $config, 'admin');
set_parameters($sel, { "User Authentication" => {"requirelogin-off" => undef} });
logout($sel);
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium();
# Set the email regexp for new bugzilla accounts to end with @bugzilla.test.
log_in($sel, $config, 'admin');
set_parameters($sel, { "User Authentication" => {"createemailregexp" => {type => "text", value => '[^@]+@bugzilla\.test$'}} });
logout($sel);
# Create a valid account. We need to randomize the login address, because a request
# expires after 3 days only and this test can be executed several times per day.
my $valid_account = 'selenium-' . random_string(10) . '@bugzilla.test';
$sel->click_ok("link=Home");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bugzilla Main Page");
$sel->is_text_present_ok("Open a New Account");
$sel->click_ok("link=Open a New Account");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Create a new Bugzilla account");
$sel->type_ok("login", $valid_account);
$sel->click_ok("send");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Request for new user account '$valid_account' submitted");
$sel->is_text_present_ok("A confirmation email has been sent");
# Try creating the same account again. It's too soon.
$sel->click_ok("link=Home");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bugzilla Main Page");
$sel->is_text_present_ok("Open a New Account");
$sel->click_ok("link=Open a New Account");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Create a new Bugzilla account");
$sel->type_ok("login", $valid_account);
$sel->click_ok("send");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Too Soon For New Token");
my $error_msg = trim($sel->get_text("error_msg"));
ok($error_msg =~ /Please wait 10 minutes/, "Too soon for this account");
# These accounts do not pass the regexp.
my @accounts = ('test@yahoo.com', 'test@bugzilla.net', 'test@bugzilla.test.com');
foreach my $account (@accounts) {
$sel->click_ok("link=New Account");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Create a new Bugzilla account");
$sel->type_ok("login", $account);
$sel->click_ok("send");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Account Creation Restricted");
$sel->is_text_present_ok("User account creation has been restricted.");
}
# These accounts are illegal.
@accounts = ('test\bugzilla@bugzilla.test', 'test@bugzilla.org@bugzilla.test', 'test@bugzilla..test');
# Logins larger than 127 characters must be rejected, for security reasons.
push @accounts, 'selenium-' . random_string(110) . '@bugzilla.test';
foreach my $account (@accounts) {
$sel->click_ok("link=New Account");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Create a new Bugzilla account");
# Starting with 5.0, the login field is a type=email and is marked "required"
# This means that we need to add the novalidate attribute to the enclosing form
# so that the illegal login can still be checked by the backend code.
my $script = q{
document.getElementById('account_creation_form').setAttribute('novalidate', 1);
};
$sel->run_script($script);
$sel->type_ok("login", $account);
$sel->click_ok("send");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Invalid Email Address");
my $error_msg = trim($sel->get_text("error_msg"));
ok($error_msg =~ /^The e-mail address you entered (\S+) didn't pass our syntax checking/, "Invalid email address detected");
}
# This account already exists.
$sel->click_ok("link=New Account");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Create a new Bugzilla account");
$sel->type_ok("login", $config->{admin_user_login});
$sel->click_ok("send");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Account Already Exists");
$error_msg = trim($sel->get_text("error_msg"));
ok($error_msg eq "There is already an account with the login name $config->{admin_user_login}.", "Account already exists");
# Turn off user account creation.
log_in($sel, $config, 'admin');
set_parameters($sel, { "User Authentication" => {"createemailregexp" => {type => "text", value => ''}} });
logout($sel);
# Make sure that links pointing to createaccount.cgi are all deactivated.
ok(!$sel->is_text_present("New Account"), "No link named 'New Account'");
$sel->click_ok("link=Home");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bugzilla Main Page");
ok(!$sel->is_text_present("Open a New Account"), "No link named 'Open a New Account'");
$sel->open_ok("/$config->{bugzilla_installation}/createaccount.cgi");
$sel->title_is("Account Creation Disabled");
$error_msg = trim($sel->get_text("error_msg"));
ok($error_msg =~ /^User account creation has been disabled. New accounts must be created by an administrator/,
"User account creation disabled");
# Re-enable user account creation.
log_in($sel, $config, 'admin');
set_parameters($sel, { "User Authentication" => {"createemailregexp" => {type => "text", value => '.*'}} });
# Make sure selenium-<random_string>@bugzilla.test has not be added to the DB yet.
go_to_admin($sel);
$sel->click_ok("link=Users");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Search users");
$sel->type_ok("matchstr", $valid_account);
$sel->click_ok("search");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Select user");
$sel->is_text_present_ok("0 users found");
logout($sel);
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium();
log_in($sel, $config, 'admin');
# Create a custom field, going through each type available,
# mark it as obsolete and delete it immediately.
go_to_admin($sel);
$sel->click_ok("link=Custom Fields");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Custom Fields");
my @types = ("Bug ID", "Large Text Box", "Free Text", "Multiple-Selection Box",
"Drop Down", "Date/Time");
my $counter = int(rand(10000));
foreach my $type (@types) {
my $fname = "cf_field" . ++$counter;
my $fdesc = "Field" . $counter;
$sel->click_ok("link=Add a new custom field");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Add a new Custom Field");
$sel->type_ok("name", $fname);
$sel->type_ok("desc", $fdesc);
$sel->select_ok("type", "label=$type");
$sel->click_ok("obsolete");
$sel->click_ok("create");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Custom Field Created");
$sel->click_ok("//a[\@href='editfields.cgi?action=del&name=$fname']");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Delete the Custom Field '$fname' ($fdesc)");
$sel->click_ok("link=Delete field '$fdesc'");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Custom Field Deleted");
}
logout($sel);
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium();
# Let's create a public and a private bug.
log_in($sel, $config, 'admin');
file_bug_in_product($sel, "TestProduct");
my $bug_summary = "Dependency Checks";
$sel->type_ok("short_desc", $bug_summary);
$sel->type_ok("comment", "This bug is public");
my $bug1_id = create_bug($sel, $bug_summary);
file_bug_in_product($sel, "TestProduct");
$sel->type_ok("alias", "secret_qa_bug_$bug1_id+1");
my $bug_summary2 = "Big Ben";
$sel->type_ok("short_desc", $bug_summary2);
$sel->type_ok("comment", "This bug is private");
$sel->type_ok("dependson", $bug1_id);
$sel->check_ok('//input[@name="groups" and @value="Master"]');
my $bug2_id = create_bug($sel, $bug_summary2);
go_to_bug($sel, $bug1_id);
$sel->click_ok("link=Mark as Duplicate");
$sel->type_ok("dup_id", $bug2_id);
edit_bug_and_return($sel, $bug1_id, $bug_summary);
$sel->is_text_present_ok("secret_qa_bug_$bug1_id+1");
logout($sel);
# A user with editbugs privs who cannot see some bugs in the dependency list
# or the bug this duplicate points to should still be able to edit this bug.
log_in($sel, $config, 'editbugs');
go_to_bug($sel, $bug1_id);
ok(!$sel->is_text_present("secret_qa_bug_$bug1_id+1"), "The alias of the private bug is not visible");
$sel->select_ok("priority", "label=High");
$sel->select_ok("bug_status", "VERIFIED");
$sel->type_ok("comment", "Can I still edit this bug?");
edit_bug($sel, $bug1_id, $bug_summary);
logout($sel);
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium();
# Very simple test script to test if bug creation with minimal data
# passes successfully for different user privileges.
#
# More elaborate tests exist in other scripts. This doesn't mean this
# one could not be improved a bit.
my $bug_summary = "Bug created by Selenium";
foreach my $user (qw(admin unprivileged canconfirm)) {
log_in($sel, $config, $user);
file_bug_in_product($sel, "TestProduct");
$sel->type_ok("short_desc", $bug_summary, "Enter bug summary");
$sel->type_ok("comment", "--- Bug created by Selenium ---", "Enter bug description");
create_bug($sel, $bug_summary);
logout($sel);
}
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium();
# Create keywords. Do some cleanup first if necessary.
log_in($sel, $config, 'admin');
go_to_admin($sel);
$sel->click_ok("link=Keywords");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Select keyword");
# If keywords already exist, delete them to not disturb the test.
my $page = $sel->get_body_text();
my @keywords = $page =~ m/(key-selenium-\w+)/gi;
foreach my $keyword (@keywords) {
my $url = $sel->get_attribute("link=$keyword\@href");
$url =~ s/action=edit/action=del/;
$sel->click_ok("//a[\@href='$url']");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Delete Keyword");
$sel->click_ok("delete");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Keyword Deleted");
}
# Now let's create our first keyword.
go_to_admin($sel);
$sel->click_ok("link=Keywords");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Select keyword");
$sel->click_ok("link=Add a new keyword");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Add keyword");
$sel->type_ok("name", "key-selenium-kone");
$sel->type_ok("description", "Hopefully an ice cream");
$sel->click_ok("create");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("New Keyword Created");
# Try create the same keyword, to check validators.
$sel->click_ok("link=Add a new keyword");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Add keyword");
$sel->type_ok("name", "key-selenium-kone");
$sel->type_ok("description", "FIX ME!");
$sel->click_ok("create");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Keyword Already Exists");
my $error_msg = trim($sel->get_text("error_msg"));
ok($error_msg eq 'A keyword with the name key-selenium-kone already exists.', 'Already created keyword');
$sel->go_back_ok();
$sel->wait_for_page_to_load(WAIT_TIME);
# Create a second keyword.
$sel->type_ok("name", "key-selenium-ktwo");
$sel->type_ok("description", "FIX ME!");
$sel->click_ok("create");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("New Keyword Created");
# Again test validators.
$sel->click_ok("link=key-selenium-ktwo");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Edit keyword");
$sel->type_ok("name", "key-selenium-kone");
$sel->type_ok("description", "the second keyword");
$sel->click_ok("update");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Keyword Already Exists");
$error_msg = trim($sel->get_text("error_msg"));
ok($error_msg eq 'A keyword with the name key-selenium-kone already exists.', 'Already created keyword');
$sel->go_back_ok();
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Edit keyword");
$sel->type_ok("name", "key-selenium-ktwo");
$sel->click_ok("update");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Keyword Updated");
# Add keywords to bugs
file_bug_in_product($sel, "TestProduct");
$sel->select_ok("component", "TestComponent");
$sel->type_ok("keywords", "key-selenium-kone");
my $bug_summary = "It's a beautiful day";
$sel->type_ok("short_desc", $bug_summary);
$sel->type_ok("comment", "This bug is to test keywords");
my $bug1_id = create_bug($sel, $bug_summary);
file_bug_in_product($sel, "TestProduct");
$sel->select_ok("component", "TestComponent");
$sel->type_ok("keywords", "key-selenium-kone, key-selenium-ktwo");
my $bug_summary2 = "Radio gaga";
$sel->type_ok("short_desc", $bug_summary2);
$sel->type_ok("comment", "This bug is also to test keywords, like bug $bug1_id");
my $bug2_id = create_bug($sel, $bug_summary2);
# Now make sure these bugs correctly appear in buglists.
open_advanced_search_page($sel);
$sel->remove_all_selections("product");
$sel->remove_all_selections("bug_status");
$sel->type_ok("keywords", "key-selenium-kone");
$sel->click_ok("Search");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Bug List");
$sel->is_text_present_ok("2 bugs found");
$sel->click_ok("link=Search");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Search for bugs");
$sel->remove_all_selections("product");
$sel->remove_all_selections("bug_status");
# Try with a different case than the one in the DB.
$sel->type_ok("keywords", "key-selenium-ktWO");
$sel->click_ok("Search");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Bug List");
$sel->is_text_present_ok("One bug found");
$sel->click_ok("link=Search");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Search for bugs");
$sel->remove_all_selections("product");
$sel->remove_all_selections("bug_status");
# Substrings also work for keywords.
$sel->type_ok("keywords", "selenium");
$sel->click_ok("Search");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Bug List");
$sel->is_text_present_ok("2 bugs found");
# Make sure describekeywords.cgi works as expected.
$sel->click_ok("link=$bug_summary");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_like(qr/^$bug1_id /);
$sel->click_ok("link=Keywords:");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Bugzilla Keyword Descriptions");
$sel->is_text_present_ok("key-selenium-kone");
$sel->is_text_present_ok("Hopefully an ice cream");
$sel->is_text_present_ok("key-selenium-ktwo");
$sel->is_text_present_ok("the second keyword");
$sel->click_ok('//a[@href="buglist.cgi?keywords=key-selenium-kone"]');
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Bug List");
$sel->is_element_present_ok("link=$bug1_id");
$sel->is_element_present_ok("link=$bug2_id");
$sel->is_text_present_ok("2 bugs found");
$sel->go_back_ok();
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->click_ok('//a[@href="buglist.cgi?keywords=key-selenium-ktwo"]');
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Bug List");
$sel->is_element_present_ok("link=$bug2_id");
$sel->is_text_present_ok("One bug found");
logout($sel);
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium();
# FIXME - At some point, this trivial script should be merged with test_create_user_accounts.t.
# Either that or we should improve this script a lot.
# Try to log in to Bugzilla using an invalid account. To be sure that the login form
# is triggered, we try to file a new bug.
go_to_home($sel, $config);
$sel->click_ok("link=New");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Log in to Bugzilla");
# The login and password are hardcoded here, because this account doesn't exist.
$sel->type_ok("Bugzilla_login", 'guest@foo.com');
$sel->type_ok("Bugzilla_password", 'foo-bar-baz');
$sel->click_ok("log_in");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Invalid Login Or Password");
$sel->is_text_present_ok("The login or password you entered is not valid.");
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium();
# 1st step: turn on usetargetmilestone and letsubmitterchoosemilestone.
log_in($sel, $config, 'admin');
set_parameters($sel, {'Bug Fields' => {'usetargetmilestone-on' => undef},
'Bug Change Policies' => {'letsubmitterchoosemilestone-on' => undef},
}
);
# 2nd step: Add the milestone "2.0" (with sortkey = 10) to the TestProduct product.
edit_product($sel, "TestProduct");
$sel->click_ok("link=Edit milestones:", undef, "Go to the Edit milestones page");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Select milestone of product 'TestProduct'", "Display milestones");
$sel->click_ok("link=Add", undef, "Go add a new milestone");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Add Milestone to Product 'TestProduct'", "Enter new milestone");
$sel->type_ok("milestone", "2.0", "Set its name to 2.0");
$sel->type_ok("sortkey", "10", "Set its sortkey to 10");
$sel->click_ok("create", undef, "Submit data");
$sel->wait_for_page_to_load(WAIT_TIME);
# If the milestone already exists, that's not a big deal. So no special action
# is required in this case.
$sel->title_is("Milestone Created", "Milestone Created");
# 3rd step: file a new bug, leaving the milestone alone (should fall back to the default one).
file_bug_in_product($sel, "TestProduct");
$sel->selected_label_is("component", "TestComponent", "Component already selected (no other component defined)");
$sel->selected_label_is("target_milestone", "---", "Default milestone selected");
$sel->selected_label_is("version", "unspecified", "Version already selected (no other version defined)");
my $bug_summary = "Target Milestone left to default";
$sel->type_ok("short_desc", $bug_summary);
$sel->type_ok("comment", "Created by Selenium to test 'musthavemilestoneonaccept'");
my $bug1_id = create_bug($sel, $bug_summary);
# 4th step: edit the bug
go_to_bug($sel, $bug1_id);
$sel->select_ok("bug_status", "label=IN_PROGRESS", "Change bug status to IN_PROGRESS");
$sel->select_ok("target_milestone", "label=2.0", "Select a non-default milestone");
edit_bug($sel, $bug1_id, $bug_summary);
# 5th step: create another bug.
file_bug_in_product($sel, "TestProduct");
$sel->select_ok("target_milestone", "label=2.0", "Set the milestone to 2.0");
$sel->selected_label_is("component", "TestComponent", "Component already selected (no other component defined)");
$sel->selected_label_is("version", "unspecified", "Version already selected (no other version defined)");
my $bug_summary2 = "Target Milestone set to non-default";
$sel->type_ok("short_desc", $bug_summary2);
$sel->type_ok("comment", "Created by Selenium to test milestone support");
my $bug2_id = create_bug($sel, $bug_summary2);
# 6th step: edit the bug
$sel->select_ok("bug_status", "label=IN_PROGRESS");
edit_bug($sel, $bug2_id, $bug_summary2);
# 7th step: test validation methods for milestones.
go_to_admin($sel);
$sel->click_ok("link=milestones");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Edit milestones for which product?");
$sel->click_ok("link=TestProduct");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Select milestone of product 'TestProduct'");
$sel->click_ok("link=2.0");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Edit Milestone '2.0' of product 'TestProduct'");
$sel->type_ok("milestone", "1.0");
$sel->value_is("milestone", "1.0");
$sel->click_ok("update");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Milestone Updated");
$sel->click_ok("link=Add");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Add Milestone to Product 'TestProduct'");
$sel->type_ok("milestone", "1.5");
$sel->value_is("milestone", "1.5");
$sel->type_ok("sortkey", "99999999999999999");
$sel->value_is("sortkey", "99999999999999999");
$sel->click_ok("create");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Invalid Milestone Sortkey");
my $error_msg = trim($sel->get_text("error_msg"));
ok($error_msg =~ /^The sortkey '99999999999999999' is not in the range/, "Invalid sortkey");
$sel->go_back_ok();
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->type_ok("sortkey", "-polu7A");
$sel->value_is("sortkey", "-polu7A");
$sel->click_ok("create");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Invalid Milestone Sortkey");
$error_msg = trim($sel->get_text("error_msg"));
ok($error_msg =~ /^The sortkey '-polu7A' is not in the range/, "Invalid sortkey");
$sel->go_back_ok();
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->click_ok("link='TestProduct'");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Select milestone of product 'TestProduct'");
$sel->click_ok("link=Delete");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Delete Milestone of Product 'TestProduct'");
$sel->is_text_present_ok("When you delete this milestone", undef, "Warn the user about bugs being affected");
$sel->click_ok("delete");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Milestone Deleted");
# 8th step: make sure the (now deleted) milestone of the bug has fallen back to the default milestone.
go_to_bug($sel, $bug1_id);
$sel->is_text_present_ok('regexp:Target Milestone:\W+---', undef, "Milestone has fallen back to the default milestone");
# 9th step: file another bug.
file_bug_in_product($sel, "TestProduct");
$sel->selected_label_is("target_milestone", "---", "Default milestone selected");
$sel->selected_label_is("component", "TestComponent");
my $bug_summary3 = "Only one Target Milestone available";
$sel->type_ok("short_desc", $bug_summary3);
$sel->type_ok("comment", "Created by Selenium to test milestone support");
my $bug3_id = create_bug($sel, $bug_summary3);
$sel->select_ok("bug_status", "label=IN_PROGRESS");
edit_bug($sel, $bug3_id, $bug_summary3);
logout($sel);
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium();
log_in($sel, $config, 'admin');
set_parameters($sel, {"Administrative Policies" => {"allowuserdeletion-on" => undef},
"User Authentication" => {"createemailregexp" => {type => "text", value => '.*'},
"emailsuffix" => {type => "text", value => ''}} });
# Set the password complexity to MIXED LETTERS.
# Password must contain at least one UPPER and one lowercase letter.
my @invalid_mixed_letter = qw(lowercase UPPERCASE 1234567890 123lowercase
123UPPERCASE !@%&^lower !@&^UPPER);
check_passwords($sel, 'mixed_letters', \@invalid_mixed_letter, ['PaSSwOrd', '%9rT#j22S']);
# Set the password complexity to LETTERS AND NUMBERS.
# Passwords must contain at least one UPPER and one lower case letter and a number.
my @invalid_letter_number = (@invalid_mixed_letter, qw(lowerUPPER 123!@%^$));
check_passwords($sel, 'letters_numbers', \@invalid_letter_number, ['-UniCode6.3', 'UNO54sun']);
# Set the password complexity to LETTERS, NUMBERS AND SPECIAL CHARACTERS.
# Passwords must contain at least one letter, a number and a special character.
my @invalid_letter_number_splchar = (qw(!@%^&~* lowerUPPER123), @invalid_letter_number);
check_passwords($sel, 'letters_numbers_specialchars', \@invalid_letter_number_splchar, ['@gu731', 'HU%m70?']);
# Set the password complexity to No Constraints.
check_passwords($sel, 'no_constraints', ['12xY!', 'aaaaa'], ['aaaaaaaa', '>F12Xy?']);
logout($sel);
sub check_passwords {
my ($sel, $param, $invalid_passwords, $valid_passwords) = @_;
set_parameters($sel, { "User Authentication" => {"password_complexity" => {type => "select", value => $param}} });
my $new_user = 'selenium-' . random_string(10) . '@bugzilla.org';
go_to_admin($sel);
$sel->click_ok("link=Users");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is('Search users');
$sel->click_ok('link=add a new user');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is('Add user');
$sel->type_ok('login', $new_user);
foreach my $password (@$invalid_passwords) {
$sel->type_ok('password', $password, 'Enter password');
$sel->click_ok('add');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
if ($param eq 'no_constraints') {
$sel->title_is('Password Too Short');
}
else {
$sel->title_is('Password Fails Requirements');
}
my $error_msg = trim($sel->get_text("error_msg"));
if ($param eq 'mixed_letters') {
ok($error_msg =~ /UPPERCASE letter.*lowercase letter/,
"Mixed letter password fails requirement: $password");
}
elsif ($param eq 'letters_numbers') {
ok($error_msg =~ /UPPERCASE letter.*lowercase letter.*digit/,
"Letter & Number password fails requirement: $password");
}
elsif ($param eq 'letters_numbers_specialchars') {
ok($error_msg =~ /letter.*special character.*digit/,
"Letter, Number & Special Character password fails requirement: $password");
}
else {
ok($error_msg =~ /The password must be at least \d+ characters long/,
"Password Too Short: $password");
}
$sel->go_back_ok();
$sel->wait_for_page_to_load_ok(WAIT_TIME);
}
my $created = 0;
foreach my $password (@$valid_passwords) {
$sel->type_ok('password', $password, 'Enter password');
$sel->click_ok($created ? 'update' : 'add');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is($created ? "User $new_user updated" : "Edit user $new_user");
my $msg = trim($sel->get_text('message'));
if ($created++) {
ok($msg =~ /A new password has been set/, 'Account updated');
}
else {
ok($msg =~ /The user account $new_user has been created successfully/, 'Account created');
}
}
return unless $created;
$sel->click_ok('delete');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Confirm deletion of user $new_user");
$sel->click_ok('delete');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("User $new_user deleted");
}
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
# We have to upload files from the local computer. This requires
# chrome privileges.
my ($sel, $config) = get_selenium(CHROME_MODE);
# set the insidergroup parameter to the admin group, and make sure
# we can view and delete attachments.
log_in($sel, $config, 'admin');
set_parameters($sel, { "Group Security" => {"insidergroup" => {type => "select", value => "admin"}},
"Attachments" => {"allow_attachment_display-on" => undef,
"allow_attachment_deletion-on" => undef}
});
# First create a new bug with a private attachment.
file_bug_in_product($sel, "TestProduct");
my $bug_summary = "Some comments are private";
$sel->type_ok("short_desc", $bug_summary);
$sel->type_ok("comment", "and some attachments too, like this one.");
$sel->check_ok("comment_is_private");
$sel->click_ok('//input[@value="Add an attachment"]');
$sel->type_ok("data", $config->{attachment_file});
$sel->type_ok("description", "private attachment, v1");
$sel->check_ok("ispatch");
my $bug1_id = create_bug($sel, $bug_summary);
$sel->is_text_present_ok("private attachment, v1 (");
$sel->is_text_present_ok("and some attachments too, like this one.");
$sel->is_checked_ok('//a[@id="comment_link_0"]/../..//div//input[@type="checkbox"]');
# Now attach a public patch to the existing bug.
$sel->click_ok("link=Add an attachment");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Create New Attachment for Bug #$bug1_id");
$sel->type_ok("data", $config->{attachment_file});
$sel->type_ok("description", "public attachment, v2");
$sel->check_ok("ispatch");
# The existing attachment name must be displayed, to mark it as obsolete.
$sel->is_text_present_ok("private attachment, v1");
$sel->type_ok("comment", "this patch is public. Everyone can see it.");
$sel->value_is("isprivate", "off");
edit_bug($sel, $bug1_id, $bug_summary, {id => "create"});
# We need to store the attachment ID.
$sel->is_text_present_ok("public attachment, v2");
my $alink = $sel->get_attribute('//a[@title="public attachment, v2"]@href');
$alink =~ /id=(\d+)/;
my $attachment1_id = $1;
$sel->is_text_present_ok("this patch is public. Everyone can see it.");
ok(!$sel->is_checked('//a[@id="comment_link_1"]/../..//div//input[@type="checkbox"]'), "Public attachment is visible");
logout($sel);
# A logged out user cannot see the private attachment, only the public one.
# Same for a user with no privs.
foreach my $user ('', 'unprivileged') {
log_in($sel, $config, $user) if $user;
go_to_bug($sel, $bug1_id);
ok(!$sel->is_text_present("private attachment, v1"), "Private attachment not visible");
$sel->is_text_present_ok("public attachment, v2");
ok(!$sel->is_text_present("and some attachments too, like this one"), "Private comment not visible");
$sel->is_text_present_ok("this patch is public. Everyone can see it.");
}
# A powerless user can comment on attachments he doesn't own.
$sel->click_ok('//a[@href="attachment.cgi?id=' . $attachment1_id . '&action=edit"]');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_like(qr/Attachment $attachment1_id Details for Bug $bug1_id/);
$sel->is_text_present_ok("created by admin");
$sel->type_ok("comment", "This attachment is not mine.");
edit_bug($sel, $bug1_id, $bug_summary, {id => "update"});
$sel->is_text_present_ok("This attachment is not mine");
# Powerless users will always be able to view their own attachments, even
# when those are marked private by a member of the insider group.
$sel->click_ok("link=Add an attachment");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Create New Attachment for Bug #$bug1_id");
$sel->type_ok("data", $config->{attachment_file});
$sel->check_ok("ispatch");
# The user doesn't have editbugs privs.
ok(!$sel->is_text_present("Check each existing attachment made obsolete by your new attachment"), "No attachments can be marked as obsolete");
$sel->type_ok("description", "My patch, which I should see, always");
$sel->type_ok("comment", "This is my patch!");
edit_bug($sel, $bug1_id, $bug_summary, {id => "create"});
$sel->is_text_present_ok("My patch, which I should see, always (");
$alink = $sel->get_attribute('//a[@title="My patch, which I should see, always"]@href');
$alink =~ /id=(\d+)/;
my $attachment2_id = $1;
$sel->is_text_present_ok("This is my patch!");
logout($sel);
# Let the admin mark the powerless user's attachment as private.
log_in($sel, $config, 'admin');
go_to_bug($sel, $bug1_id);
$sel->click_ok('//a[@href="attachment.cgi?id=' . $attachment2_id . '&action=edit"]');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_like(qr/Attachment $attachment2_id Details for Bug $bug1_id/);
$sel->check_ok("isprivate");
$sel->type_ok("comment", "Making the powerless user's patch private.");
edit_bug($sel, $bug1_id, $bug_summary, {id => "update"});
$sel->is_text_present_ok("My patch, which I should see, always (");
$sel->is_checked_ok('//a[@id="comment_link_4"]/../..//div//input[@type="checkbox"]');
$sel->is_text_present_ok("Making the powerless user's patch private.");
logout($sel);
# A logged out user cannot see private attachments.
go_to_bug($sel, $bug1_id);
ok(!$sel->is_text_present("private attachment, v1"), "Private attachment not visible to logged out users");
ok(!$sel->is_text_present("My patch, which I should see, always ("), "Private attachment not visible to logged out users");
$sel->is_text_present_ok("This is my patch!");
ok(!$sel->is_text_present("Making the powerless user's patch private"), "Private comment not visible to logged out users");
# A powerless user can only see private attachments he owns.
log_in($sel, $config, 'unprivileged');
go_to_bug($sel, $bug1_id);
$sel->is_text_present_ok("My patch, which I should see, always (");
$sel->click_ok("link=My patch, which I should see, always");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
# No title displayed while viewing an attachment.
$sel->title_is("");
$sel->go_back_ok();
$sel->wait_for_page_to_load_ok(WAIT_TIME);
logout($sel);
# Admins can delete attachments.
log_in($sel, $config, 'admin');
go_to_bug($sel, $bug1_id);
$sel->click_ok('//a[@href="attachment.cgi?id=' . $attachment2_id . '&action=edit"]');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_like(qr/Attachment $attachment2_id Details for Bug $bug1_id/);
$sel->click_ok("link=Delete");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Delete Attachment $attachment2_id of Bug $bug1_id");
$sel->is_text_present_ok("Do you really want to delete this attachment?");
$sel->type_ok("reason", "deleted by Selenium");
edit_bug_and_return($sel, $bug1_id, $bug_summary, {id => "delete"});
$sel->is_text_present_ok("deleted by Selenium");
$sel->click_ok("link=attachment $attachment2_id");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Attachment Removed");
$sel->is_text_present_ok("The attachment you are attempting to access has been removed");
set_parameters($sel, {
"Group Security" => {"insidergroup" => { type => "select",
value => "QA-Selenium-TEST" }},
});
logout($sel);
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium();
# First make sure the 'My QA query' saved search is gone.
log_in($sel, $config, 'admin');
if ($sel->is_text_present("My QA query")) {
$sel->click_ok("link=My QA query");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug List: My QA query");
$sel->click_ok("forget_search");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Search is gone");
$sel->is_text_present_ok("OK, the My QA query search is gone.");
}
# Enable the QA contact field and file a new bug restricted to the 'Master' group
# with a powerless user as the QA contact. He should only be able to access the
# bug if the QA contact field is enabled, else he looses this privilege.
set_parameters($sel, { "Bug Fields" => {"useqacontact-on" => undef} });
file_bug_in_product($sel, 'TestProduct');
$sel->type_ok("qa_contact", $config->{unprivileged_user_login}, "Set the powerless user as QA contact");
my $bug_summary = "Test for QA contact";
$sel->type_ok("short_desc", $bug_summary);
$sel->type_ok("comment", "This is a test to check QA contact privs.");
$sel->check_ok('//input[@name="groups" and @value="Master"]');
my $bug1_id = create_bug($sel, $bug_summary);
# Create a saved search querying for all bugs with the powerless user
# as QA contact.
open_advanced_search_page($sel);
$sel->remove_all_selections_ok("product");
$sel->add_selection_ok("product", "TestProduct");
$sel->remove_all_selections("bug_status");
$sel->select_ok("f1", "label=QA Contact");
$sel->select_ok("o1", "label=is equal to");
$sel->type_ok("v1", $config->{unprivileged_user_login}, "Look for the powerless user as QA contact");
$sel->click_ok("Search");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug List");
$sel->is_element_present_ok("b$bug1_id", undef, "Bug $bug1_id is on the list");
$sel->is_text_present_ok("Test for QA contact");
$sel->type_ok("save_newqueryname", "My QA query");
$sel->click_ok("remember");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Search created");
my $text = trim($sel->get_text("message"));
ok($text =~ /OK, you have a new search named My QA query/, "New saved search 'My QA query'");
$sel->click_ok("link=My QA query");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug List: My QA query");
$sel->is_element_present_ok("b$bug1_id", undef, "Bug $bug1_id is on the list");
$sel->is_text_present_ok("Test for QA contact");
# The saved search should still work, even with the QA contact field disabled.
# ("work" doesn't mean you should still see all bugs, depending on your role
# and privs!)
set_parameters($sel, { "Bug Fields" => {"useqacontact-off" => undef} });
$sel->click_ok("link=My QA query");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug List: My QA query");
$sel->is_text_present_ok("One bug found");
$sel->is_element_present_ok("b$bug1_id", undef, "Bug $bug1_id is on the list");
$sel->click_ok("link=$bug1_id");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_like(qr/^$bug1_id /);
# The 'QA Contact' label must not be displayed.
ok(!$sel->is_text_present("QA Contact"), "The QA Contact label is not present");
logout($sel);
# You cannot access the bug when being logged out, as it's restricted
# to the Master group.
$sel->type_ok("quicksearch_top", $bug1_id);
$sel->click_ok("find_top");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug Access Denied");
$sel->is_text_present_ok("You are not authorized to access bug");
# You are still not allowed to access the bug when logged in as the
# powerless user, as the QA contact field is disabled.
# Don't use it log_in() as we want to follow this specific link.
$sel->click_ok("link=log in to an account", undef, "Log in");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Log in to Bugzilla");
$sel->is_text_present_ok("Bugzilla needs a legitimate login and password to continue");
$sel->type_ok("Bugzilla_login", $config->{unprivileged_user_login}, "Enter login name");
$sel->type_ok("Bugzilla_password", $config->{unprivileged_user_passwd}, "Enter password");
$sel->click_ok("log_in", undef, "Submit credentials");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug Access Denied");
$sel->is_text_present_ok("You are not authorized to access bug");
logout($sel);
# Re-enable the QA contact field.
log_in($sel, $config, 'admin');
set_parameters($sel, { "Bug Fields" => {"useqacontact-on" => undef} });
logout($sel);
# Log in as the powerless user. As the QA contact field is enabled again,
# you can now access the restricted bug.
log_in($sel, $config, 'unprivileged');
$sel->click_ok("link=Preferences");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("General Preferences");
$sel->select_ok("state_addselfcc", "value=never");
$sel->click_ok("update");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("General Preferences");
open_advanced_search_page($sel);
$sel->remove_all_selections_ok("product");
$sel->add_selection_ok("product", "TestProduct");
$sel->remove_all_selections_ok("bug_status");
$sel->select_ok("f1", "label=QA Contact");
$sel->select_ok("o1", "label=is equal to");
$sel->type_ok("v1", $config->{unprivileged_user_login}, "Look for the powerless user as QA contact");
$sel->click_ok("Search");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug List");
$sel->is_text_present_ok("One bug found");
$sel->is_element_present_ok("b$bug1_id", undef, "Bug $bug1_id is on the list");
$sel->is_text_present_ok("Test for QA contact");
$sel->click_ok("link=$bug1_id");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_like(qr/$bug1_id /);
$sel->click_ok("bz_qa_contact_edit_action");
$sel->value_is("qa_contact", $config->{unprivileged_user_login}, "The powerless user is the current QA contact");
$sel->check_ok("set_default_qa_contact");
edit_bug($sel, $bug1_id, $bug_summary);
# The user is no longer the QA contact, and he has no other role
# with the bug. He can no longer see it.
$sel->is_text_present_ok("(list of e-mails not available)");
$sel->click_ok("link=$bug1_id");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug Access Denied");
logout($sel);
$sel->stop();
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium();
# Turn on 'requirelogin'.
log_in($sel, $config, 'admin');
set_parameters($sel, { "User Authentication" => {"requirelogin-on" => undef} });
logout($sel);
# We try to access each page. None of the ones listed below should
# let you view it without being logged in.
my @pages = qw(admin attachment buglist chart colchange describecomponents
describekeywords duplicates editclassifications editcomponents
editfields editflagtypes editgroups editkeywords editmilestones
editparams editproducts editsettings editusers editvalues
editversions editwhines editworkflow enter_bug page post_bug
process_bug query quips report reports request sanitycheck
search_plugin show_activity show_bug showdependencygraph
showdependencytree summarize_time userprefs votes);
foreach my $page (@pages) {
$sel->open_ok("/$config->{bugzilla_installation}/${page}.cgi");
if ($page ne 'votes' || $config->{test_extensions}) {
$sel->title_is("Log in to Bugzilla");
}
else {
$sel->title_is("Extension Disabled");
}
}
# Those have parameters passed to the page, so we put them here separately.
@pages = ("query.cgi?format=report-table", "query.cgi?format=report-graph",
"votes.cgi?action=show_user", "votes.cgi?action=show_bug");
foreach my $page (@pages) {
$sel->open_ok("/$config->{bugzilla_installation}/$page");
if ($page !~ /^votes/ || $config->{test_extensions}) {
$sel->title_is("Log in to Bugzilla");
}
else {
$sel->title_is("Extension Disabled");
}
}
# These pages should still be accessible.
@pages = ("config.cgi", "createaccount.cgi", "index.cgi", "relogin.cgi",
"token.cgi?a=reqpw&loginname=" . $config->{unprivileged_user_login});
foreach my $page (@pages) {
$sel->open_ok("/$config->{bugzilla_installation}/$page");
$sel->title_isnt("Log in to Bugzilla");
}
# Turn off 'requirelogin'.
log_in($sel, $config, 'admin');
set_parameters($sel, { "User Authentication" => {"requirelogin-off" => undef} });
logout($sel);
# Make sure we can access random pages again.
$sel->click_ok("link=Search");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_isnt("Log in to Bugzilla");
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium();
log_in($sel, $config, 'admin');
go_to_admin($sel);
$sel->click_ok("link=Sanity Check", undef, "Go to Sanity Check (no parameter)");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Sanity Check", "Display sanitycheck.cgi");
$sel->is_text_present_ok("Sanity check completed.", undef, "Page displayed correctly");
my @args = qw(rebuildvotecache createmissinggroupcontrolmapentries repair_creation_date
repair_bugs_fulltext remove_invalid_bug_references repair_bugs_fulltext
remove_invalid_attach_references remove_old_whine_targets rescanallBugMail);
foreach my $arg (@args) {
$sel->open_ok("/$config->{bugzilla_installation}/sanitycheck.cgi?$arg=1");
$sel->title_is("Suspicious Action", "Calling sanitycheck.cgi with no token triggers a confirmation page");
$sel->click_ok("confirm", "Confirm the action");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Sanity Check", "Calling sanitycheck.cgi with $arg=1");
if ($arg eq 'rescanallBugMail') {
# sanitycheck.cgi always stops after looking for unsent bugmail. So we cannot rely on
# "Sanity check completed." to determine if an error has been thrown or not.
$sel->is_text_present_ok("found with possibly unsent mail", undef, "Look for unsent bugmail");
ok(!$sel->is_text_present("Software error"), "No error thrown");
}
else {
$sel->is_text_present_ok("Sanity check completed.", undef, "Page displayed correctly");
}
}
logout($sel);
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium();
# If a saved search named 'SavedSearchTEST1' exists, remove it.
log_in($sel, $config, 'QA_Selenium_TEST');
$sel->click_ok("link=Preferences");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("General Preferences");
$sel->click_ok("link=Saved Searches");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Saved Searches");
if($sel->is_text_present("SavedSearchTEST1")) {
# There is no other way to identify this link (as they are all named "Forget").
$sel->click_ok('//a[contains(@href,"buglist.cgi?cmdtype=dorem&remaction=forget&namedcmd=SavedSearchTEST1")]');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Search is gone");
$sel->is_text_present_ok("OK, the SavedSearchTEST1 search is gone.");
}
# Create a new saved search.
open_advanced_search_page($sel);
$sel->type_ok("short_desc", "test search");
$sel->click_ok("Search");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug List");
$sel->type_ok("save_newqueryname", "SavedSearchTEST1");
$sel->click_ok("remember");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Search created");
my $text = trim($sel->get_text("message"));
ok($text =~ /OK, you have a new search named SavedSearchTEST1./, "New search named SavedSearchTEST1 has been created");
$sel->click_ok("link=SavedSearchTEST1");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug List: SavedSearchTEST1");
# Remove the saved search from the page footer. It should no longer be displayed there.
$sel->click_ok("link=Preferences");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("General Preferences");
$sel->click_ok("link=Saved Searches");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Saved Searches");
$sel->is_text_present_ok("SavedSearchTEST1");
$sel->uncheck_ok('//input[@type="checkbox" and @alt="SavedSearchTEST1"]');
# $sel->value_is("//input[\@type='checkbox' and \@alt='SavedSearchTEST1']", "off");
$sel->click_ok("update");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Saved Searches");
$text = trim($sel->get_text("message"));
ok($text =~ /The changes to your saved searches have been saved./, "Saved searches changes have been saved");
# Modify the saved search. Said otherwise, we should still be able to save
# a new search with exactly the same name.
open_advanced_search_page($sel);
$sel->type_ok("short_desc", "bilboa");
$sel->click_ok("Search");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug List");
# As we said, this saved search should no longer be displayed in the page footer.
ok(!$sel->is_text_present("SavedSearchTEST1"), "SavedSearchTEST1 is not present in the page footer");
$sel->type_ok("save_newqueryname", "SavedSearchTEST1");
$sel->click_ok("remember");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Search updated");
$text = trim($sel->get_text("message"));
ok($text =~ /Your search named SavedSearchTEST1 has been updated./, "Saved searche SavedSearchTEST1 has been updated.");
# Make sure our new criteria has been saved (let's edit the saved search).
# As the saved search is no longer displayed in the footer, we have to go
# to the "Preferences" page to edit it.
$sel->click_ok("link=Preferences");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("General Preferences");
$sel->click_ok("link=Saved Searches");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Saved Searches");
$sel->is_text_present_ok("SavedSearchTEST1");
$sel->click_ok('//a[@href="buglist.cgi?cmdtype=dorem&remaction=run&namedcmd=SavedSearchTEST1"]');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug List: SavedSearchTEST1");
$sel->click_ok("edit_search");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Search for bugs");
$sel->value_is("short_desc", "bilboa");
$sel->go_back_ok();
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->click_ok("forget_search");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Search is gone");
$text = trim($sel->get_text("message"));
ok($text =~ /OK, the SavedSearchTEST1 search is gone./, "The SavedSearchTEST1 search is gone.");
logout($sel);
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use QA::Util;
use Test::More "no_plan";
my ($sel, $config) = get_selenium();
# TODO: This test really needs improvement. There is by far much more stuff
# to test in this area.
# First, a very trivial search, which returns no result.
go_to_home($sel, $config);
open_advanced_search_page($sel);
$sel->type_ok("short_desc", "ois£jdfm#sd%fasd!fm", "Type a non-existent string in the bug summary field");
$sel->click_ok("Search");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Bug List");
$sel->is_text_present_ok("Zarro Boogs found");
# Display all available columns. Look for all bugs assigned to a user who doesn't exist.
$sel->open_ok("/$config->{bugzilla_installation}/buglist.cgi?quicksearch=%40xx45ft&columnlist=all");
$sel->title_is("Bug List");
$sel->is_text_present_ok("Zarro Boogs found");
# Now some real tests.
log_in($sel, $config, 'canconfirm');
file_bug_in_product($sel, "TestProduct");
my $bug_summary = "Update this summary with this bug ID";
$sel->type_ok("short_desc", $bug_summary);
$sel->type_ok("comment", "I'm supposed to appear in the coming buglist.");
my $bug1_id = create_bug($sel, $bug_summary);
$sel->click_ok("summary_edit_action");
$bug_summary .= ": my ID is $bug1_id";
$sel->type_ok("short_desc", $bug_summary);
$sel->type_ok("comment", "Updating bug summary....");
edit_bug($sel, $bug1_id, $bug_summary);
# Test pronoun substitution.
open_advanced_search_page($sel);
$sel->remove_all_selections("bug_status");
$sel->remove_all_selections("resolution");
$sel->type_ok("short_desc", "my ID is $bug1_id");
$sel->select_ok("f1", "label=Commenter");
$sel->select_ok("o1", "label=is equal to");
$sel->type_ok("v1", "%user%");
$sel->click_ok("add_button");
$sel->select_ok("f2", "label=Comment");
$sel->select_ok("o2", "label=contains the string");
$sel->type_ok("v2", "coming buglist");
$sel->click_ok("Search");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug List");
$sel->is_text_present_ok("One bug found");
$sel->is_text_present_ok("Update this summary with this bug ID: my ID is $bug1_id");
logout($sel);
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium(CHROME_MODE);
my $urlbase = $config->{bugzilla_installation};
my $admin_user = $config->{admin_user_login};
# Let's create a bug and attachment to play with.
log_in($sel, $config, 'admin');
file_bug_in_product($sel, "TestProduct");
my $bug_summary = "Security checks";
$sel->type_ok("short_desc", $bug_summary);
$sel->type_ok("comment", "This bug will be used to test security fixes.");
$sel->type_ok("data", $config->{attachment_file});
$sel->type_ok("description", "simple patch, v1");
$sel->click_ok("ispatch");
my $bug1_id = create_bug($sel, $bug_summary);
#######################################################################
# Security bug 38862.
#######################################################################
# No alternate host for attachments; cookies will be accessible.
set_parameters($sel, { "Attachments" => {"allow_attachment_display-on" => undef,
"reset-attachment_base" => undef} });
go_to_bug($sel, $bug1_id);
$sel->click_ok("link=Add an attachment");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Create New Attachment for Bug #$bug1_id");
$sel->type_ok("attach_text", "<html>\n<head>\n<title>I want your cookies</title>\n<head>\n" .
"<body>\n<script type='text/javascript'>document.write(document.cookie);</script>\n" .
"</body>\n</html>", "Writing text into the attachment textarea");
$sel->type_ok("description", "show my cookies");
edit_bug($sel, $bug1_id, $bug_summary, {id => "create"});
my $alink = $sel->get_attribute('//a[@title="show my cookies"]@href');
$alink =~ /id=(\d+)/;
my $attach1_id = $1;
$sel->click_ok("link=Attachment #$attach1_id");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_like(qr/Attachment $attach1_id Details for Bug $bug1_id/);
$sel->click_ok("link=edit details");
$sel->type_ok("contenttypeentry", "text/html");
edit_bug($sel, $bug1_id, $bug_summary, {id => "update"});
$sel->click_ok("link=show my cookies");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("I want your cookies");
my @cookies = split(/[\s;]+/, $sel->get_body_text());
my $nb_cookies = scalar @cookies;
ok($nb_cookies, "Found $nb_cookies cookies:\n" . join("\n", @cookies));
ok(!$sel->is_cookie_present("Bugzilla_login"), "Bugzilla_login not accessible");
ok(!$sel->is_cookie_present("Bugzilla_logincookie"), "Bugzilla_logincookie not accessible");
$sel->go_back_ok();
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_like(qr/^$bug1_id /);
# Alternate host for attachments; no cookie should be accessible.
set_parameters($sel, { "Attachments" => {"attachment_base" => {type => "text",
value => "http://127.0.0.1/$urlbase"}} });
go_to_bug($sel, $bug1_id);
$sel->click_ok("link=show my cookies");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("I want your cookies");
@cookies = split(/[\s;]+/, $sel->get_body_text());
$nb_cookies = scalar @cookies;
ok(!$nb_cookies, "No cookies found");
ok(!$sel->is_cookie_present("Bugzilla_login"), "Bugzilla_login not accessible");
ok(!$sel->is_cookie_present("Bugzilla_logincookie"), "Bugzilla_logincookie not accessible");
$sel->go_back_ok();
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_like(qr/^$bug1_id /);
set_parameters($sel, { "Attachments" => {"reset-attachment_base" => undef} });
#######################################################################
# Security bug 472362.
#######################################################################
$sel->click_ok("link=Preferences");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("General Preferences");
my $admin_cookie = $sel->get_value("token");
logout($sel);
log_in($sel, $config, 'editbugs');
$sel->click_ok("link=Preferences");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("General Preferences");
my $editbugs_cookie = $sel->get_value("token");
# Using our own unused token is fine.
$sel->open_ok("/$urlbase/userprefs.cgi?dosave=1&display_quips=off&token=$editbugs_cookie");
$sel->title_is("General Preferences");
$sel->is_text_present_ok("The changes to your general preferences have been saved");
# Reusing a token must fail. They must all trigger the Suspicious Action warning.
my @args = ("", "token=", "token=i123x", "token=$admin_cookie", "token=$editbugs_cookie");
foreach my $arg (@args) {
$sel->open_ok("/$urlbase/userprefs.cgi?dosave=1&display_quips=off&$arg");
$sel->title_is("Suspicious Action");
if ($arg eq "token=$admin_cookie") {
$sel->is_text_present_ok("Generated by: admin <$admin_user>");
$sel->is_text_present_ok("This token has not been generated by you");
}
else {
$sel->is_text_present_ok("It looks like you didn't come from the right page");
}
}
logout($sel);
#######################################################################
# Security bug 529416.
#######################################################################
log_in($sel, $config, 'admin');
file_bug_in_product($sel, "TestProduct");
$sel->type_ok("alias", "secret_qa_bug_" . ($bug1_id + 1));
my $bug_summary2 = "Private QA Bug";
$sel->type_ok("short_desc", $bug_summary2);
$sel->type_ok("comment", "This private bug is used to test security fixes.");
$sel->type_ok("dependson", $bug1_id);
$sel->check_ok('//input[@name="groups" and @value="Master"]');
my $bug2_id = create_bug($sel, $bug_summary2);
go_to_bug($sel, $bug1_id);
$sel->is_text_present_ok("secret_qa_bug_$bug2_id");
logout($sel);
log_in($sel, $config, 'editbugs');
go_to_bug($sel, $bug1_id);
ok(!$sel->is_text_present("secret_qa_bug_$bug2_id"), "The alias 'secret_qa_bug_$bug2_id' is not visible for unauthorized users");
$sel->is_text_present_ok($bug2_id);
logout($sel);
go_to_bug($sel, $bug1_id);
ok(!$sel->is_text_present("secret_qa_bug_$bug2_id"), "The alias 'secret_qa_bug_$bug2_id' is not visible for logged out users");
$sel->is_text_present_ok($bug2_id);
#######################################################################
# Security bug 472206.
# Keep this test as the very last one as the File Saver will remain
# open till the end of the script. Selenium is currently* unable
# to interact with it and close it (* = 2.6.0).
#######################################################################
log_in($sel, $config, 'admin');
set_parameters($sel, { "Attachments" => {"allow_attachment_display-off" => undef} });
# Attachments are not viewable.
go_to_bug($sel, $bug1_id);
$sel->click_ok("link=Details");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_like(qr/Attachment \d+ Details for Bug $bug1_id/);
$sel->is_text_present_ok("The attachment is not viewable in your browser due to security restrictions");
$sel->click_ok("link=View");
# Wait 1 second to give the browser a chance to display the attachment.
# Do not use wait_for_page_to_load_ok() as the File Saver will never go away.
sleep(1);
ok(!$sel->is_text_present('@@'), "Patch not displayed");
# Enable viewing attachments.
set_parameters($sel, { "Attachments" => {"allow_attachment_display-on" => undef} });
go_to_bug($sel, $bug1_id);
$sel->click_ok('link=simple patch, v1');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("");
$sel->is_text_present_ok('@@');
$sel->go_back_ok();
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_like(qr/$bug1_id /);
logout($sel);
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium();
# Set the querysharegroup param to be the canconfirm group.
log_in($sel, $config, 'admin');
set_parameters($sel, { "Group Security" => {"querysharegroup" => {type => "select", value => "canconfirm"}} });
# Create new saved search and call it 'Shared Selenium buglist'.
$sel->type_ok("quicksearch_top", ":TestProduct Selenium");
$sel->click_ok("find_top");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug List");
$sel->type_ok("save_newqueryname", "Shared Selenium buglist");
$sel->click_ok("remember");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Search created");
my $text = trim($sel->get_text("message"));
ok($text =~ /OK, you have a new search named Shared Selenium buglist./, "New search named 'Shared Selenium buglist' has been created");
# Retrieve the newly created saved search's internal ID and make sure it's displayed
# in the footer by default.
$sel->click_ok("link=Preferences");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("General Preferences");
$sel->click_ok("link=Saved Searches");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Saved Searches");
my $ssname = $sel->get_attribute('//input[@type="checkbox" and @alt="Shared Selenium buglist"]@name');
$ssname =~ /(?:link_in_footer_(\d+))/;
my $saved_search1_id = $1;
$sel->is_checked_ok("link_in_footer_$saved_search1_id");
# As an admin, the "Add to footer" checkbox must be displayed, but unchecked by default.
$sel->select_ok("share_$saved_search1_id", "label=canconfirm");
ok(!$sel->is_checked("force_$saved_search1_id"), "Shared search not displayed in other users' footer by default");
$sel->click_ok("force_$saved_search1_id");
$sel->click_ok("update");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Saved Searches");
logout($sel);
# Log in as the "canconfirm" user. The search shared by the admin must appear
# in the footer.
log_in($sel, $config, 'canconfirm');
$sel->is_text_present_ok("Shared Selenium buglist");
$sel->click_ok("link=Shared Selenium buglist");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug List: Shared Selenium buglist");
# You cannot delete other users' saved searches.
ok(!$sel->is_element_present("forget_search"), "'Forget...' button not available");
# The name of the sharer must appear in the "Saved Searches" section.
$sel->click_ok("link=Preferences");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("General Preferences");
$sel->click_ok("link=Saved Searches");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Saved Searches");
$sel->is_text_present_ok($config->{admin_user_login});
# Remove the shared search from your footer.
$sel->is_checked_ok("link_in_footer_$saved_search1_id");
$sel->click_ok("link_in_footer_$saved_search1_id");
$sel->click_ok("update");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Saved Searches");
# Go to a page where the query name is unlikely to appear in the main page.
$sel->click_ok("link=Permissions");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Permissions");
ok(!$sel->is_text_present("Shared Selenium buglist"), "Shared query no longer displayed in the footer");
# Create your own saved search, and share it with the canconfirm group.
$sel->type_ok("quicksearch_top", ":TestProduct sw:helpwanted");
$sel->click_ok("find_top");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug List");
$sel->type_ok("save_newqueryname", "helpwanted");
$sel->click_ok("remember");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Search created");
$text = trim($sel->get_text("message"));
ok($text =~ /OK, you have a new search named helpwanted./, "New search named helpwanted has been created");
$sel->click_ok("link=Preferences");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("General Preferences");
$sel->click_ok("link=Saved Searches");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Saved Searches");
$ssname = $sel->get_attribute('//input[@type="checkbox" and @alt="helpwanted"]@name');
$ssname =~ /(?:link_in_footer_(\d+))/;
my $saved_search2_id = $1;
# Our own saved searches are displayed in the footer by default.
$sel->is_checked_ok("link_in_footer_$saved_search2_id");
$sel->select_ok("share_$saved_search2_id", "label=canconfirm");
$sel->click_ok("update");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Saved Searches");
logout($sel);
# Log in as admin again. The other user is not a blesser for the 'canconfirm'
# group, and so his shared search must not be displayed by default. But it
# must still be available and can be added to the footer, if desired.
log_in($sel, $config, 'admin');
ok(!$sel->is_text_present("helpwanted"), "No 'helpwanted' shared search displayed");
$sel->click_ok("link=Preferences");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("General Preferences");
$sel->click_ok("link=Saved Searches");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Saved Searches");
$sel->is_text_present_ok("helpwanted");
$sel->is_text_present_ok($config->{canconfirm_user_login});
ok(!$sel->is_checked("link_in_footer_$saved_search2_id"), "Shared query available but not displayed");
$sel->click_ok("link_in_footer_$saved_search2_id");
$sel->click_ok("update");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Saved Searches");
# This query is now available from the footer.
$sel->click_ok("link=helpwanted");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug List: helpwanted");
# Remove the 'Shared Selenium buglist' query.
$sel->click_ok("link=Preferences");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("General Preferences");
$sel->click_ok("link=Saved Searches");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Saved Searches");
# There is no better way to identify the link
$sel->click_ok('//a[contains(@href,"buglist.cgi?cmdtype=dorem&remaction=forget&namedcmd=Shared%20Selenium%20buglist")]',
undef, "Deleting the 'Shared Selenium buglist' search");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Search is gone");
$text = trim($sel->get_text("message"));
ok($text =~ /OK, the Shared Selenium buglist search is gone./, "The 'Shared Selenium buglist' search is gone");
logout($sel);
# Make sure that the 'helpwanted' query is not shared with the QA_Selenium_TEST
# user as he doesn't belong to the 'canconfirm' group.
log_in($sel, $config, 'QA_Selenium_TEST');
ok(!$sel->is_text_present("helpwanted"), "The 'helpwanted' query is not displayed in the footer");
$sel->click_ok("link=Preferences");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("General Preferences");
$sel->click_ok("link=Saved Searches");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Saved Searches");
ok(!$sel->is_text_present("helpwanted"), "The 'helpwanted' query is not shared with this user");
logout($sel);
# Now remove the 'helpwanted' saved search.
log_in($sel, $config, 'canconfirm');
$sel->click_ok("link=Preferences");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("General Preferences");
$sel->click_ok("link=Saved Searches");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Saved Searches");
ok(!$sel->is_text_present("Shared Selenium buglist"), "The 'Shared Selenium buglist' is no longer available");
$sel->click_ok('//a[contains(@href,"buglist.cgi?cmdtype=dorem&remaction=forget&namedcmd=helpwanted")]',
undef, "Deleting the 'helpwanted' search");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Search is gone");
$text = trim($sel->get_text("message"));
ok($text =~ /OK, the helpwanted search is gone./, "The 'helpwanted' search is gone");
logout($sel);
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium();
log_in($sel, $config, 'admin');
set_parameters($sel, { "Bug Fields" => {"useclassification-on" => undef} });
# Do not use file_bug_in_product() because our goal here is not to file
# a bug but to check what is present in the UI, and also to make sure
# that we get exactly the right page with the right information.
#
# The admin is not a member of the "QA‑Selenium‑TEST" group, and so
# cannot see the "QA‑Selenium‑TEST" product.
$sel->click_ok("link=New");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->is_text_present_ok("Select Classification");
my $full_text = trim($sel->get_body_text());
ok($full_text =~ /All: Show all products/, "The 'All' link is displayed");
$sel->click_ok("link=All");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->is_text_present_ok("Select Product");
ok(!$sel->is_text_present("QA-Selenium-TEST"), "The QA-Selenium-TEST product is not displayed");
logout($sel);
# Same steps, but for a member of the "QA‑Selenium‑TEST" group.
# The "QA‑Selenium‑TEST" product must be visible to him.
log_in($sel, $config, 'QA_Selenium_TEST');
$sel->click_ok("link=New");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->is_text_present_ok("Select Classification");
$sel->click_ok("link=All");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->is_text_present_ok("Select Product");
$sel->is_text_present_ok("QA-Selenium-TEST");
$sel->click_ok('//a[contains(@href, "product=QA-Selenium-TEST")]');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Enter Bug: QA-Selenium-TEST");
logout($sel);
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium();
log_in($sel, $config, 'admin');
set_parameters($sel, { "General" => {shutdownhtml => {type => "text",
value => "I'm down (set by test_shutdown.t)" }
} });
# None of the following pages should be accessible when Bugzilla is down.
my @pages = qw(admin attachment buglist chart colchange config createaccount
describecomponents describekeywords duplicates
editclassifications editcomponents editfields editflagtypes
editgroups editkeywords editmilestones editproducts editsettings
editusers editvalues editversions editwhines editworkflow
enter_bug index page post_bug process_bug query quips relogin
report reports request sanitycheck search_plugin show_activity
show_bug showdependencygraph showdependencytree summarize_time
token userprefs votes xmlrpc);
foreach my $page (@pages) {
$sel->open_ok("/$config->{bugzilla_installation}/${page}.cgi");
$sel->title_is("Bugzilla is Down");
}
# Those have parameters passed to the page, so we put them here separately.
@pages = ("query.cgi?format=report-table", "query.cgi?format=report-graph",
"votes.cgi?action=show_user", "votes.cgi?action=show_bug");
foreach my $page (@pages) {
$sel->open_ok("/$config->{bugzilla_installation}/$page");
$sel->title_is("Bugzilla is Down");
}
# Clear 'shutdownhtml', to re-enable Bugzilla.
# At this point, the admin has been logged out. We cannot use log_in(),
# nor set_parameters(), due to shutdownhtml being active.
$sel->open_ok("/$config->{bugzilla_installation}/editparams.cgi");
$sel->title_is("Log in to Bugzilla");
$sel->type_ok("Bugzilla_login", $config->{admin_user_login}, "Enter admin login name");
$sel->type_ok("Bugzilla_password", $config->{admin_user_passwd}, "Enter admin password");
$sel->click_ok("log_in");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Configuration: Required Settings");
$sel->click_ok("link=General");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Configuration: General");
$sel->type_ok("shutdownhtml", "");
$sel->click_ok('//input[@type="submit" and @value="Save Changes"]', undef, "Save Changes");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Parameters Updated");
# Accessing index.cgi should work again now.
$sel->click_ok("link=Home");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bugzilla Main Page");
logout($sel);
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium();
log_in($sel, $config, 'admin');
set_parameters($sel, {'Bug Fields' => {'usestatuswhiteboard-on' => undef}});
# Make sure the status whiteboard is displayed and add stuff to it.
file_bug_in_product($sel, "TestProduct");
$sel->select_ok("component", "TestComponent");
my $bug_summary = "white and black";
$sel->type_ok("short_desc", $bug_summary);
$sel->type_ok("comment", "This bug is to test the status whiteboard");
my $bug1_id = create_bug($sel, $bug_summary);
$sel->is_text_present_ok("Whiteboard:");
$sel->type_ok("status_whiteboard", "[msg from test_status_whiteboard.t: x77v]");
edit_bug($sel, $bug1_id, $bug_summary);
file_bug_in_product($sel, "TestProduct");
$sel->select_ok("component", "TestComponent");
my $bug_summary2 = "WTC";
$sel->type_ok("short_desc", $bug_summary2);
$sel->type_ok("comment", "bugzillation!");
my $bug2_id = create_bug($sel, $bug_summary2);
$sel->type_ok("status_whiteboard", "[msg from test_status_whiteboard.t: x77v]");
edit_bug($sel, $bug2_id, $bug_summary2);
# Now search these bugs above using data being in the status whiteboard,
# and save the query.
open_advanced_search_page($sel);
$sel->remove_all_selections_ok("product");
$sel->remove_all_selections_ok("bug_status");
$sel->type_ok("status_whiteboard", "x77v");
$sel->click_ok("Search");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug List");
$sel->is_text_present_ok("2 bugs found");
$sel->type_ok("save_newqueryname", "sw-x77v");
$sel->click_ok("remember");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Search created");
my $text = trim($sel->get_text("message"));
ok($text =~ /you have a new search named sw-x77v/, 'Saved search correctly saved');
# Make sure the saved query works.
$sel->click_ok("link=sw-x77v");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug List: sw-x77v");
$sel->is_text_present_ok("2 bugs found");
# The status whiteboard should no longer be displayed in both the query
# and bug view pages (query.cgi and show_bug.cgi) when usestatuswhiteboard
# is off.
set_parameters($sel, {'Bug Fields' => {'usestatuswhiteboard-off' => undef}});
$sel->click_ok("link=Search");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Search for bugs");
ok(!$sel->is_text_present("Whiteboard:"), "Whiteboard label no longer displayed in the search page");
go_to_bug($sel, $bug1_id);
ok(!$sel->is_text_present("Whiteboard:"), "Whiteboard label no longer displayed in the bug page");
# Queries based on the status whiteboard should still work when
# the parameter is off.
$sel->click_ok("link=sw-x77v");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug List: sw-x77v");
$sel->is_text_present_ok("2 bugs found");
# Turn on usestatuswhiteboard again as some other scripts may expect the status
# whiteboard to be available by default.
set_parameters($sel, {'Bug Fields' => {'usestatuswhiteboard-on' => undef}});
# Clear the status whiteboard and delete the saved search.
$sel->click_ok("link=sw-x77v");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug List: sw-x77v");
$sel->is_text_present_ok("2 bugs found");
$sel->click_ok("mass_change");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug List");
$sel->click_ok("check_all");
$sel->type_ok("status_whiteboard", "");
$sel->click_ok("commit");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bugs processed");
$sel->click_ok("link=sw-x77v");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug List: sw-x77v");
$sel->is_text_present_ok("Zarro Boogs found");
$sel->click_ok("forget_search");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Search is gone");
$sel->is_text_present_ok("OK, the sw-x77v search is gone.");
logout($sel);
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium();
my $qa_user = $config->{QA_Selenium_TEST_user_login};
my $no_privs_user = $config->{unprivileged_user_login};
log_in($sel, $config, 'admin');
set_parameters($sel, { "Group Security" => {"strict_isolation-on" => undef} });
# Restrict the bug to the "Master" group, so that we can check that only
# allowed people can be CC'ed to the bug.
file_bug_in_product($sel, 'Another Product');
$sel->select_ok("component", "label=c2");
$sel->select_ok("version", "label=Another2");
my $bug_summary = "Test isolation";
$sel->type_ok("short_desc", $bug_summary);
$sel->type_ok("comment", "Unallowed users refused");
my $master_gid = $sel->get_attribute('//input[@type="checkbox" and @name="groups" and @value="Master"]@id');
$sel->check_ok($master_gid);
$master_gid =~ s/group_//;
my $bug1_id = create_bug($sel, $bug_summary);
# At that point, CANEDIT is off and so everybody can be CC'ed to the bug.
$sel->click_ok("cc_edit_area_showhide");
$sel->type_ok("newcc", "$qa_user, $no_privs_user");
edit_bug_and_return($sel, $bug1_id, $bug_summary);
$sel->click_ok("cc_edit_area_showhide");
$sel->add_selection_ok("cc", "label=$no_privs_user");
$sel->add_selection_ok("cc", "label=$qa_user");
$sel->check_ok("removecc");
edit_bug($sel, $bug1_id, $bug_summary);
# Now enable CANEDIT for the "Master" group. This will enable strict isolation
# for the product.
edit_product($sel, "Another Product");
$sel->click_ok("link=Edit Group Access Controls:");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Edit Group Controls for Another Product");
$sel->check_ok("canedit_$master_gid");
$sel->click_ok("submit");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Update group access controls for Another Product");
# Non-members can no longer be CC'ed to the bug.
go_to_bug($sel, $bug1_id);
$sel->click_ok("cc_edit_area_showhide");
$sel->type_ok("newcc", $no_privs_user);
$sel->click_ok("commit");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Invalid User Group");
$sel->is_text_present_ok("User '$no_privs_user' is not able to edit the 'Another Product' Product");
$sel->go_back_ok();
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_like(qr/^$bug1_id /);
$sel->click_ok("cc_edit_area_showhide");
$sel->type_ok("newcc", $qa_user);
$sel->click_ok("commit");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Invalid User Group");
$sel->is_text_present_ok("User '$qa_user' is not able to edit the 'Another Product' Product");
# Now set QA_Selenium_TEST user as a member of the Master group.
go_to_admin($sel);
$sel->click_ok("link=Users");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Search users");
$sel->type_ok("matchstr", $qa_user);
$sel->select_ok("matchtype", "label=exact (find this user)");
$sel->click_ok("search");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Edit user QA-Selenium-TEST <$qa_user>");
$sel->check_ok("group_$master_gid");
$sel->click_ok("update");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("User $qa_user updated");
# The QA_Selenium_TEST user can now be CC'ed to the bug.
go_to_bug($sel, $bug1_id);
$sel->click_ok("cc_edit_area_showhide");
$sel->type_ok("newcc", $qa_user);
edit_bug_and_return($sel, $bug1_id, $bug_summary);
$sel->click_ok("cc_edit_area_showhide");
$sel->add_selection_ok("cc", "label=$qa_user");
$sel->check_ok("removecc");
edit_bug_and_return($sel, $bug1_id, $bug_summary);
# The powerless user still cannot be CC'ed.
$sel->click_ok("cc_edit_area_showhide");
$sel->type_ok("newcc", "$qa_user, $no_privs_user");
$sel->click_ok("commit");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Invalid User Group");
$sel->is_text_present_ok("User '$no_privs_user' is not able to edit the 'Another Product' Product");
# Reset parameters back to defaults.
set_parameters($sel, { "Group Security" => {"strict_isolation-off" => undef} });
go_to_admin($sel);
$sel->click_ok("link=Users");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Search users");
$sel->type_ok("matchstr", $qa_user);
$sel->select_ok("matchtype", "label=exact (find this user)");
$sel->click_ok("search");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Edit user QA-Selenium-TEST <$qa_user>");
$sel->uncheck_ok("group_$master_gid");
$sel->click_ok("update");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("User $qa_user updated");
edit_product($sel, "Another Product");
$sel->click_ok("link=Edit Group Access Controls:");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Edit Group Controls for Another Product");
$sel->uncheck_ok("canedit_$master_gid");
$sel->click_ok("submit");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Update group access controls for Another Product");
logout($sel);
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium();
# Turn on the usevisibilitygroups param so that some users are invisible.
log_in($sel, $config, 'admin');
set_parameters($sel, { "Group Security" => {"usevisibilitygroups-on" => undef} });
# You can see all users from editusers.cgi, but once you leave this page,
# usual group visibility restrictions apply and the "powerless" user cannot
# be sudo'ed as he is in no group.
go_to_admin($sel);
$sel->click_ok("link=Users");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Search users");
$sel->type_ok("matchstr", $config->{unprivileged_user_login});
$sel->select_ok("matchtype", "label=exact (find this user)");
$sel->click_ok("search");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Edit user no-privs <$config->{unprivileged_user_login}>");
$sel->value_is("login", $config->{unprivileged_user_login});
$sel->click_ok("link=Impersonate this user");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Begin sudo session");
$sel->value_is("target_login", $config->{unprivileged_user_login});
$sel->type_ok("reason", "Selenium test about sudo sessions");
$sel->type_ok("password", $config->{admin_user_passwd}, "Enter admin password");
$sel->click_ok('//input[@value="Begin Session"]');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Match Failed");
my $error_msg = trim($sel->get_text("error_msg"));
ok($error_msg eq "$config->{unprivileged_user_login} does not exist or you are not allowed to see that user.",
"Cannot impersonate users you cannot see");
# Turn off the usevisibilitygroups param so that all users are visible again.
set_parameters($sel, { "Group Security" => {"usevisibilitygroups-off" => undef} });
# The "powerless" user can now be sudo'ed.
go_to_admin($sel);
$sel->click_ok("link=Users");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Search users");
$sel->type_ok("matchstr", $config->{unprivileged_user_login});
$sel->select_ok("matchtype", "label=exact (find this user)");
$sel->click_ok("search");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Edit user no-privs <$config->{unprivileged_user_login}>");
$sel->value_is("login", $config->{unprivileged_user_login});
$sel->click_ok("link=Impersonate this user");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Begin sudo session");
$sel->value_is("target_login", $config->{unprivileged_user_login});
$sel->type_ok("password", $config->{admin_user_passwd}, "Enter admin password");
$sel->click_ok('//input[@value="Begin Session"]');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Sudo session started");
my $text = trim($sel->get_text("message"));
ok($text =~ /The sudo session has been started/, "The sudo session has been started");
# Make sure this user is not an admin and has no privs at all, and that
# he cannot access editusers.cgi (despite the sudoer can).
$sel->click_ok("link=Preferences");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("General Preferences");
$sel->click_ok("link=Permissions");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Permissions");
$sel->is_text_present_ok("There are no permission bits set on your account");
# We access the page directly as there is no link pointing to it.
$sel->open_ok("/$config->{bugzilla_installation}/editusers.cgi");
$sel->title_is("Authorization Required");
$error_msg = trim($sel->get_text("error_msg"));
ok($error_msg =~ /^Sorry, you aren't a member of the 'editusers' group/, "Not a member of the editusers group");
$sel->click_ok("link=end session");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Sudo session complete");
$sel->is_text_present_ok("Your sudo session has ended");
# Try to access the sudo page directly, with no credentials.
$sel->open_ok("/$config->{bugzilla_installation}/relogin.cgi?action=begin-sudo&target_login=$config->{admin_user_login}");
$sel->title_is("Password Required");
# Now try to start a sudo session directly, with all required credentials.
$sel->open_ok("/$config->{bugzilla_installation}/relogin.cgi?action=begin-sudo&password=$config->{admin_user_passwd}&target_login=$config->{unprivileged_user_login}", undef, "Impersonate a user directly by providing all required data");
# A direct access to the page is supposed to have no Referer header set,
# which would trigger the "Untrusted Authentication Request" error, but
# due to the way Selenium works, the Referer header is set and the
# "Preparation Required" error is thrown instead. In any case, one of
# those two errors must be thrown.
my $title = $sel->get_title();
ok($title eq "Untrusted Authentication Request" || $title eq "Preparation Required", $title);
# Now try to sudo an admin, which is not allowed.
$sel->open_ok("/$config->{bugzilla_installation}/relogin.cgi?action=prepare-sudo&target_login=$config->{admin_user_login}");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Begin sudo session");
$sel->value_is("target_login", $config->{admin_user_login});
$sel->type_ok("reason", "Selenium hack");
$sel->type_ok("password", $config->{admin_user_passwd}, "Enter admin password");
$sel->click_ok('//input[@value="Begin Session"]');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("User Protected");
$error_msg = trim($sel->get_text("error_msg"));
ok($error_msg =~ /^The user $config->{admin_user_login} may not be impersonated by sudoers/, "Cannot impersonate administrators");
# Now try to sudo a non-existing user account, with no password.
$sel->go_back_ok();
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Begin sudo session");
# Starting with 5.0, the password field is a type=password and is marked
# "required". This means that we need to remove the required attribute from
# the input so that it can still be checked by the backend code.
my $script = q{
document.getElementById('password').removeAttribute('required');
};
$sel->run_script($script);
$sel->type_ok("target_login", 'foo@bar.com');
$sel->click_ok('//input[@value="Begin Session"]');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Password Required");
# Same as above, but with your password.
$sel->open_ok("/$config->{bugzilla_installation}/relogin.cgi?action=prepare-sudo&target_login=foo\@bar.com");
$sel->title_is("Begin sudo session");
$sel->value_is("target_login", 'foo@bar.com');
$sel->type_ok("password", $config->{admin_user_passwd}, "Enter admin password");
$sel->click_ok('//input[@value="Begin Session"]');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Match Failed");
$error_msg = trim($sel->get_text("error_msg"));
ok($error_msg eq 'foo@bar.com does not exist or you are not allowed to see that user.', "Cannot impersonate non-existing accounts");
logout($sel);
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium();
log_in($sel, $config, 'admin');
set_parameters($sel, { "Bug Fields" => {"usetargetmilestone-on" => undef} });
# Create a new milestone to the 'TestProduct' product.
edit_product($sel, "TestProduct");
$sel->click_ok("link=Edit milestones:");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Select milestone of product 'TestProduct'");
$sel->click_ok("link=Add");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Add Milestone to Product 'TestProduct'");
$sel->type_ok("milestone", "TM1");
$sel->type_ok("sortkey", "10");
$sel->click_ok("create");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Milestone Created");
# Edit the milestone of bugs.
file_bug_in_product($sel, "TestProduct");
$sel->select_ok("component", "TestComponent");
my $bug_summary = "stone and rock";
$sel->type_ok("short_desc", $bug_summary);
$sel->type_ok("comment", "This bug is to test milestones");
my $bug1_id = create_bug($sel, $bug_summary);
$sel->is_text_present_ok("Target Milestone:");
$sel->select_ok("target_milestone", "label=TM1");
edit_bug($sel, $bug1_id, $bug_summary);
# Query for bugs with the TM1 milestone.
open_advanced_search_page($sel);
$sel->is_text_present_ok("Target Milestone:");
$sel->remove_all_selections_ok("product");
$sel->add_selection_ok("product", "label=TestProduct");
$sel->add_selection_ok("target_milestone", "label=TM1");
$sel->click_ok("Search");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug List");
$sel->is_text_present_ok("One bug found");
$sel->type_ok("save_newqueryname", "selenium_m0");
$sel->click_ok("remember");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Search created");
my $text = trim($sel->get_text("message"));
ok($text =~ /OK, you have a new search named selenium_m0./, "New search named selenium_m0 has been created");
# Turn off milestones and check that the milestone field no longer appears in bugs.
set_parameters($sel, { "Bug Fields" => {"usetargetmilestone-off" => undef} });
$sel->click_ok("link=Search");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Search for bugs");
ok(!$sel->is_text_present("Target:"), "The target milestone field is no longer displayed in the search page");
go_to_bug($sel, $bug1_id);
ok(!$sel->is_text_present("Target Milestone:"), "The milestone field is no longer displayed in the bug page");
# The existing query must still work despite milestones are off now.
$sel->click_ok("link=selenium_m0");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug List: selenium_m0");
$sel->is_text_present_ok("One bug found");
$sel->click_ok("forget_search");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Search is gone");
$text = trim($sel->get_text("message"));
ok($text =~ /OK, the selenium_m0 search is gone./, "The selenium_m0 search is gone");
# Re-enable the usetargetmilestone parameter and delete the created
# milestone from the Testproduct product.
set_parameters($sel, { "Bug Fields" => {"usetargetmilestone-on" => undef} });
edit_product($sel, "TestProduct");
$sel->click_ok("link=Edit milestones:");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Select milestone of product 'TestProduct'");
$sel->click_ok('//a[@href="editmilestones.cgi?action=del&product=TestProduct&milestone=TM1"]',
undef, "Deleting the TM1 milestone");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Delete Milestone of Product 'TestProduct'");
$text = trim($sel->get_body_text());
ok($text =~ /There is 1 bug entered for this milestone/, "Warning displayed about 1 bug targetted to TM1");
$sel->click_ok("delete");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Milestone Deleted");
logout($sel);
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium();
# Set the timetracking group to "editbugs", which is the default value for this parameter.
log_in($sel, $config, 'admin');
set_parameters($sel, { "Group Security" => {"timetrackinggroup" => {type => "select", value => "editbugs"}} });
# Add some Hours Worked to a bug so that we are sure at least one bug
# will be present in our buglist below.
file_bug_in_product($sel, "TestProduct");
$sel->select_ok("component", "TestComponent");
my $bug_summary = "Rocket science";
$sel->type_ok("short_desc", $bug_summary);
$sel->type_ok("comment", "Time flies");
my $bug1_id = create_bug($sel, $bug_summary);
$sel->type_ok("work_time", 2.6);
$sel->type_ok("comment", "I did some work");
edit_bug_and_return($sel, $bug1_id, $bug_summary);
$sel->is_text_present_ok("I did some work");
$sel->is_text_present_ok("Additional hours worked: 2.6");
# Let's call summarize_time.cgi directly, with no parameters.
$sel->open_ok("/$config->{bugzilla_installation}/summarize_time.cgi");
$sel->title_is("No Bugs Selected");
my $error_msg = trim($sel->get_text("error_msg"));
ok($error_msg =~ /You apparently didn't choose any bugs for viewing/, "No data displayed");
# Search for bugs which have some value in the Hours Worked field.
open_advanced_search_page($sel);
$sel->remove_all_selections("bug_status");
$sel->select_ok("f1", "label=Hours Worked");
$sel->select_ok("o1", "label=is greater than");
$sel->type_ok("v1", "0");
$sel->click_ok("Search");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Bug List");
$sel->is_text_present_ok("found");
# Test dates passed to summarize_time.cgi.
$sel->click_ok("timesummary");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_like(qr/^Time Summary \(\d+ bugs selected\)/);
$sel->check_ok("monthly");
$sel->check_ok("detailed");
$sel->type_ok("start_date", "2009-01-01");
$sel->type_ok("end_date", "2009-04-30");
$sel->click_ok("summarize");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_like(qr/^Time Summary \(\d+ bugs selected\)/);
$sel->is_text_present_ok('regexp:Total of \d+\.\d+ hours worked');
$sel->is_text_present_ok("2009-01-01 to 2009-01-31");
$sel->is_text_present_ok("2009-02-01 to 2009-02-28");
$sel->is_text_present_ok("2009-04-01 to 2009-04-30");
$sel->type_ok("end_date", "2009-04-as");
$sel->click_ok("summarize");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Illegal Date");
$error_msg = trim($sel->get_text("error_msg"));
ok($error_msg =~ /'2009-04-as' is not a legal date/, "Illegal end date");
# Now display one bug only. We cannot do careful checks, because
# the page sums up contributions made by the same user during the same
# month, and so running this script several times per month would
# break checks we may want to do (e.g. by making sure that the contribution
# above has been taken into account). So we are just making sure that
# the page is displayed and throws no error.
go_to_bug($sel, $bug1_id);
$sel->click_ok("//a[contains(text(),'Summarize time')]");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Time Summary for Bug $bug1_id");
$sel->check_ok("inactive");
$sel->check_ok("owner");
$sel->click_ok("summarize");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Time Summary for Bug $bug1_id");
logout($sel);
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use FindBin qw($RealBin);
use lib "$RealBin/../lib";
use Test::More "no_plan";
use QA::Util;
my ($sel, $config) = get_selenium();
log_in($sel, $config, 'admin');
set_parameters($sel, { "Administrative Policies" => {"allowuserdeletion-on" => undef} });
# First delete test users, if not deleted correctly during a previous run.
cleanup_users($sel);
# The Master group inherits privs of the Slave group.
go_to_admin($sel);
$sel->click_ok("link=Groups");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Edit Groups");
$sel->click_ok("link=Master");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Change Group: Master");
my $group_url = $sel->get_location();
$group_url =~ /group=(\d+)$/;
my $master_gid = $1;
go_to_admin($sel);
$sel->click_ok("link=Groups");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Edit Groups");
$sel->click_ok("link=Add Group");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Add group");
$sel->type_ok("name", "Slave");
$sel->type_ok("desc", "Members of the Master group are also members of this group");
$sel->uncheck_ok("isactive");
ok(!$sel->is_checked("insertnew"), "Group not added to products by default");
$sel->click_ok("create");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("New Group Created");
my $slave_gid = $sel->get_value("group_id");
$sel->add_selection_ok("members_add", "label=Master");
$sel->click_ok('//input[@value="Update Group"]');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Change Group: Slave");
# Create users.
go_to_admin($sel);
$sel->click_ok("link=Users");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is('Search users');
$sel->click_ok('link=add a new user');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is('Add user');
$sel->type_ok('login', 'master@selenium.bugzilla.org');
$sel->type_ok('name', 'master-user');
$sel->type_ok('password', 'selenium', 'Enter password');
$sel->type_ok('disabledtext', 'Not for common usage');
$sel->click_ok('add');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is('Edit user master-user <master@selenium.bugzilla.org>');
$sel->check_ok("//input[\@name='group_$master_gid']");
$sel->click_ok('update');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is('User master@selenium.bugzilla.org updated');
$sel->is_text_present_ok('The account has been added to the Master group');
$sel->click_ok("link=add a new user");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is('Add user');
$sel->type_ok('login', 'slave@selenium.bugzilla.org');
$sel->type_ok('name', 'slave-user');
$sel->type_ok('password', 'selenium', 'Enter password');
$sel->type_ok('disabledtext', 'Not for common usage');
$sel->click_ok('add');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is('Edit user slave-user <slave@selenium.bugzilla.org>');
$sel->check_ok("//input[\@name='group_$slave_gid']");
$sel->click_ok('update');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is('User slave@selenium.bugzilla.org updated');
$sel->is_text_present_ok('The account has been added to the Slave group');
$sel->click_ok("link=add a new user");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is('Add user');
$sel->type_ok('login', 'reg@selenium.bugzilla.org');
$sel->type_ok('name', 'reg-user');
$sel->type_ok('password', 'selenium', 'Enter password');
$sel->type_ok('disabledtext', 'Not for common usage');
$sel->click_ok('add');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is('Edit user reg-user <reg@selenium.bugzilla.org>');
# Disabled accounts are not listed by default.
$sel->click_ok('link=find other users');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is('Search users');
$sel->select_ok('is_enabled', 'label=Enabled');
$sel->click_ok('search');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
ok(!$sel->is_text_present('master@selenium.bugzilla.org'), 'Inactive user account master-user not listed by default');
ok(!$sel->is_text_present('slave@selenium.bugzilla.org'), 'Inactive user account slave-user not listed by default');
ok(!$sel->is_text_present('reg@selenium.bugzilla.org'), 'Inactive user account reg-user not displayed by default');
# Now make sure group inheritance works correctly.
$sel->click_ok('link=find other users');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is('Search users');
$sel->check_ok('grouprestrict');
$sel->select_ok('groupid', 'label=Master');
$sel->select_ok('matchtype', 'value=substr');
$sel->select_ok('is_enabled', 'label=All');
$sel->click_ok('search');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->is_text_present_ok('master@selenium.bugzilla.org', 'master-user in Master group');
ok(!$sel->is_text_present('slave@selenium.bugzilla.org'), 'slave-user not in Master group');
ok(!$sel->is_text_present('reg@selenium.bugzilla.org'), 'reg-user not in Master group');
$sel->click_ok('link=find other users');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is('Search users');
$sel->check_ok('grouprestrict');
$sel->select_ok('groupid', 'label=Slave');
$sel->select_ok('matchtype', 'value=substr');
$sel->select_ok('is_enabled', 'label=All');
$sel->click_ok('search');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->is_text_present_ok('master@selenium.bugzilla.org', 'master-user in Slave group');
$sel->is_text_present_ok('slave@selenium.bugzilla.org', 'slave-user in Slave group');
ok(!$sel->is_text_present('reg@selenium.bugzilla.org'), 'reg-user not in Slave group');
# Add a regular expression to the Slave group.
go_to_admin($sel);
$sel->click_ok("link=Groups");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Edit Groups");
$sel->click_ok('link=Slave');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is('Change Group: Slave');
$sel->type_ok('regexp', '^reg\@.*$');
$sel->click_ok('//input[@value="Update Group"]');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Change Group: Slave");
# Test group inheritance again.
go_to_admin($sel);
$sel->click_ok("link=Users");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is('Search users');
$sel->check_ok('grouprestrict');
$sel->select_ok('groupid', 'label=Master');
$sel->select_ok('matchtype', 'value=substr');
$sel->select_ok('is_enabled', 'label=All');
$sel->click_ok('search');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->is_text_present_ok('master@selenium.bugzilla.org', 'master-user in Master group');
ok(!$sel->is_text_present('slave@selenium.bugzilla.org'), 'slave-user not in Master group');
ok(!$sel->is_text_present('reg@selenium.bugzilla.org'), 'reg-user not in Master group');
$sel->click_ok('link=find other users');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is('Search users');
$sel->check_ok('grouprestrict');
$sel->select_ok('groupid', 'label=Slave');
$sel->select_ok('matchtype', 'value=substr');
$sel->select_ok('is_enabled', 'label=All');
$sel->click_ok('search');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->is_text_present_ok('master@selenium.bugzilla.org', 'master-user in Slave group');
$sel->is_text_present_ok('slave@selenium.bugzilla.org', 'slave-user in Slave group');
$sel->is_text_present_ok('reg@selenium.bugzilla.org', 'reg-user in Slave group');
# Remove created users and groups.
cleanup_users($sel);
cleanup_groups($sel, $slave_gid);
logout($sel);
sub cleanup_users {
my $sel = shift;
go_to_admin($sel);
$sel->click_ok("link=Users");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Search users");
$sel->type_ok('matchstr', '(master|slave|reg)@selenium.bugzilla.org');
$sel->select_ok('matchtype', 'value=regexp');
$sel->select_ok('is_enabled', 'label=All');
$sel->click_ok("search");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Select user");
foreach my $user ('master', 'slave', 'reg') {
my $login = $user . '@selenium.bugzilla.org';
next unless $sel->is_text_present($login);
$sel->click_ok("link=$login");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Edit user ${user}-user <$login>");
$sel->click_ok("delete");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Confirm deletion of user $login");
ok(!$sel->is_text_present('You cannot delete this user account'), 'The user can be safely deleted');
$sel->click_ok("delete");
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("User $login deleted");
$sel->click_ok('link=show the user list again');
$sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is('Select user');
}
}
sub cleanup_groups {
my ($sel, $slave_gid) = @_;
go_to_admin($sel);
$sel->click_ok("link=Groups");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Edit Groups");
$sel->click_ok("//a[\@href='editgroups.cgi?action=del&group=$slave_gid']");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Delete group 'Slave'");
$sel->is_text_present_ok("Do you really want to delete this group?");
ok(!$sel->is_element_present("removeusers"), 'No direct members in this group');
$sel->click_ok("delete");
$sel->wait_for_page_to_load(WAIT_TIME);
$sel->title_is("Group Deleted");
$sel->is_text_present_ok("The group Slave has been deleted.");
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment