From a6238e079b4e8e62d3e23f019e0895c626133c83 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Thu, 25 Jun 2015 03:35:16 +0000 Subject: Bug 1144485: Adapt upstream Selenium test suite to BMO --- qa/config/checksetup_answers.txt | 26 + qa/config/generate_test_data.pl | 822 +++++++++++++++++++++ qa/config/patch.diff | 18 + qa/config/selenium_test.conf | 49 ++ qa/extensions/QA/Config.pm | 20 + qa/extensions/QA/Extension.pm | 71 ++ qa/extensions/QA/lib/Util.pm | 25 + .../en/default/pages/qa/email_in.html.tmpl | 7 + .../QA/template/en/default/qa/create_bug.txt.tmpl | 17 + .../en/default/qa/create_bug_with_headers.txt.tmpl | 33 + .../QA/template/en/default/qa/results.html.tmpl | 28 + .../QA/template/en/default/qa/update_bug.txt.tmpl | 13 + .../en/default/qa/update_bug_with_headers.txt.tmpl | 29 + qa/t/lib/QA/RPC.pm | 284 +++++++ qa/t/lib/QA/RPC/JSONRPC.pm | 168 +++++ qa/t/lib/QA/RPC/XMLRPC.pm | 19 + qa/t/lib/QA/Tests.pm | 108 +++ qa/t/lib/QA/Util.pm | 375 ++++++++++ qa/t/selenium_server_start.t | 83 +++ qa/t/selenium_server_stop.t | 34 + qa/t/test_bmo_autolinkification.t | 53 ++ qa/t/test_bmo_enter_new_bug.t | 421 +++++++++++ qa/t/test_bmo_retire_values.t | 388 ++++++++++ qa/t/test_bug_edit.t | 504 +++++++++++++ qa/t/test_choose_priority.t | 27 + qa/t/test_classifications.t | 146 ++++ qa/t/test_config.t | 45 ++ qa/t/test_create_user_accounts.t | 129 ++++ qa/t/test_custom_fields.t | 459 ++++++++++++ qa/t/test_custom_fields_admin.t | 53 ++ qa/t/test_default_groups.t | 210 ++++++ qa/t/test_dependencies.t | 53 ++ qa/t/test_edit_products_properties.t | 361 +++++++++ qa/t/test_email_preferences.t | 400 ++++++++++ qa/t/test_enter_new_bug.t | 35 + qa/t/test_flags.t | 482 ++++++++++++ qa/t/test_flags2.t | 344 +++++++++ qa/t/test_groups.t | 323 ++++++++ qa/t/test_keywords.t | 176 +++++ qa/t/test_login.t | 32 + qa/t/test_long_list_redirection.t | 20 + qa/t/test_milestones.t | 170 +++++ qa/t/test_private_attachments.t | 200 +++++ qa/t/test_qa_contact.t | 167 +++++ qa/t/test_require_login.t | 81 ++ qa/t/test_sanity_check.t | 46 ++ qa/t/test_saved_searches.t | 114 +++ qa/t/test_search.t | 71 ++ qa/t/test_security.t | 177 +++++ qa/t/test_shared_searches.t | 196 +++++ qa/t/test_show_all_products.t | 57 ++ qa/t/test_shutdown.t | 75 ++ qa/t/test_status_whiteboard.t | 98 +++ qa/t/test_strict_isolation.t | 155 ++++ qa/t/test_sudo_sessions.t | 143 ++++ qa/t/test_target_milestones.t | 109 +++ qa/t/test_time_summary.t | 100 +++ qa/t/test_user_groups.t | 229 ++++++ qa/t/test_user_matching.t | 188 +++++ qa/t/test_user_preferences.t | 237 ++++++ qa/t/test_user_privs.t | 68 ++ qa/t/test_votes.t | 251 +++++++ qa/t/webservice_bug_add_attachment.t | 227 ++++++ qa/t/webservice_bug_add_comment.t | 168 +++++ qa/t/webservice_bug_attachments.t | 151 ++++ qa/t/webservice_bug_comments.t | 175 +++++ qa/t/webservice_bug_create.t | 239 ++++++ qa/t/webservice_bug_fields.t | 219 ++++++ qa/t/webservice_bug_get.t | 146 ++++ qa/t/webservice_bug_get_bugs.t | 146 ++++ qa/t/webservice_bug_history.t | 29 + qa/t/webservice_bug_legal_values.t | 100 +++ qa/t/webservice_bug_search.t | 185 +++++ qa/t/webservice_bug_update.t | 683 +++++++++++++++++ qa/t/webservice_bug_update_see_also.t | 82 ++ qa/t/webservice_bugzilla.t | 45 ++ qa/t/webservice_group_create.t | 97 +++ qa/t/webservice_jsonp.t | 30 + qa/t/webservice_product.t | 109 +++ qa/t/webservice_product_create.t | 163 ++++ qa/t/webservice_product_get.t | 109 +++ qa/t/webservice_user_create.t | 108 +++ qa/t/webservice_user_get.t | 218 ++++++ qa/t/webservice_user_login_logout.t | 124 ++++ qa/t/webservice_user_offer_account_by_email.t | 59 ++ 85 files changed, 13434 insertions(+) create mode 100644 qa/config/checksetup_answers.txt create mode 100644 qa/config/generate_test_data.pl create mode 100644 qa/config/patch.diff create mode 100644 qa/config/selenium_test.conf create mode 100644 qa/extensions/QA/Config.pm create mode 100644 qa/extensions/QA/Extension.pm create mode 100644 qa/extensions/QA/lib/Util.pm create mode 100644 qa/extensions/QA/template/en/default/pages/qa/email_in.html.tmpl create mode 100644 qa/extensions/QA/template/en/default/qa/create_bug.txt.tmpl create mode 100644 qa/extensions/QA/template/en/default/qa/create_bug_with_headers.txt.tmpl create mode 100644 qa/extensions/QA/template/en/default/qa/results.html.tmpl create mode 100644 qa/extensions/QA/template/en/default/qa/update_bug.txt.tmpl create mode 100644 qa/extensions/QA/template/en/default/qa/update_bug_with_headers.txt.tmpl create mode 100644 qa/t/lib/QA/RPC.pm create mode 100644 qa/t/lib/QA/RPC/JSONRPC.pm create mode 100644 qa/t/lib/QA/RPC/XMLRPC.pm create mode 100644 qa/t/lib/QA/Tests.pm create mode 100644 qa/t/lib/QA/Util.pm create mode 100644 qa/t/selenium_server_start.t create mode 100644 qa/t/selenium_server_stop.t create mode 100644 qa/t/test_bmo_autolinkification.t create mode 100644 qa/t/test_bmo_enter_new_bug.t create mode 100644 qa/t/test_bmo_retire_values.t create mode 100644 qa/t/test_bug_edit.t create mode 100644 qa/t/test_choose_priority.t create mode 100644 qa/t/test_classifications.t create mode 100644 qa/t/test_config.t create mode 100644 qa/t/test_create_user_accounts.t create mode 100644 qa/t/test_custom_fields.t create mode 100644 qa/t/test_custom_fields_admin.t create mode 100644 qa/t/test_default_groups.t create mode 100644 qa/t/test_dependencies.t create mode 100644 qa/t/test_edit_products_properties.t create mode 100644 qa/t/test_email_preferences.t create mode 100644 qa/t/test_enter_new_bug.t create mode 100644 qa/t/test_flags.t create mode 100644 qa/t/test_flags2.t create mode 100644 qa/t/test_groups.t create mode 100644 qa/t/test_keywords.t create mode 100644 qa/t/test_login.t create mode 100644 qa/t/test_long_list_redirection.t create mode 100644 qa/t/test_milestones.t create mode 100644 qa/t/test_private_attachments.t create mode 100644 qa/t/test_qa_contact.t create mode 100644 qa/t/test_require_login.t create mode 100644 qa/t/test_sanity_check.t create mode 100644 qa/t/test_saved_searches.t create mode 100644 qa/t/test_search.t create mode 100644 qa/t/test_security.t create mode 100644 qa/t/test_shared_searches.t create mode 100644 qa/t/test_show_all_products.t create mode 100644 qa/t/test_shutdown.t create mode 100644 qa/t/test_status_whiteboard.t create mode 100644 qa/t/test_strict_isolation.t create mode 100644 qa/t/test_sudo_sessions.t create mode 100644 qa/t/test_target_milestones.t create mode 100644 qa/t/test_time_summary.t create mode 100644 qa/t/test_user_groups.t create mode 100644 qa/t/test_user_matching.t create mode 100644 qa/t/test_user_preferences.t create mode 100644 qa/t/test_user_privs.t create mode 100644 qa/t/test_votes.t create mode 100644 qa/t/webservice_bug_add_attachment.t create mode 100644 qa/t/webservice_bug_add_comment.t create mode 100644 qa/t/webservice_bug_attachments.t create mode 100644 qa/t/webservice_bug_comments.t create mode 100644 qa/t/webservice_bug_create.t create mode 100644 qa/t/webservice_bug_fields.t create mode 100644 qa/t/webservice_bug_get.t create mode 100644 qa/t/webservice_bug_get_bugs.t create mode 100644 qa/t/webservice_bug_history.t create mode 100644 qa/t/webservice_bug_legal_values.t create mode 100644 qa/t/webservice_bug_search.t create mode 100644 qa/t/webservice_bug_update.t create mode 100644 qa/t/webservice_bug_update_see_also.t create mode 100644 qa/t/webservice_bugzilla.t create mode 100644 qa/t/webservice_group_create.t create mode 100644 qa/t/webservice_jsonp.t create mode 100644 qa/t/webservice_product.t create mode 100644 qa/t/webservice_product_create.t create mode 100644 qa/t/webservice_product_get.t create mode 100644 qa/t/webservice_user_create.t create mode 100644 qa/t/webservice_user_get.t create mode 100644 qa/t/webservice_user_login_logout.t create mode 100644 qa/t/webservice_user_offer_account_by_email.t (limited to 'qa') diff --git a/qa/config/checksetup_answers.txt b/qa/config/checksetup_answers.txt new file mode 100644 index 000000000..adafe8c43 --- /dev/null +++ b/qa/config/checksetup_answers.txt @@ -0,0 +1,26 @@ +$answer{'ADMIN_EMAIL'} = 'admin@mozilla.bugs'; +$answer{'ADMIN_OK'} = 'Y'; +$answer{'ADMIN_PASSWORD'} = 'password'; +$answer{'ADMIN_REALNAME'} = 'QA Admin'; +$answer{'NO_PAUSE'} = 1; +$answer{'bugzilla_version'} = '1'; +$answer{'create_htaccess'} = ''; +$answer{'cvsbin'} = '/usr/bin/cvs'; +$answer{'db_check'} = 1; +$answer{'db_driver'} = '%DB%'; +$answer{'db_host'} = 'localhost'; +$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{'db_name'} = '%DB_NAME%', +$answer{'db_pass'} = 'bugs'; +$answer{'db_port'} = 0; +$answer{'db_sock'} = ''; +$answer{'db_user'} = 'bugs'; +$answer{'diffpath'} = '/usr/bin'; +$answer{'index_html'} = 0; +$answer{'interdiffbin'} = '/usr/bin/interdiff'; +$answer{'urlbase'} = 'http://localhost/bmo/'; +$answer{'use_suexec'} = ''; +$answer{'webservergroup'} = '%USER%'; diff --git a/qa/config/generate_test_data.pl b/qa/config/generate_test_data.pl new file mode 100644 index 000000000..2c6afe03a --- /dev/null +++ b/qa/config/generate_test_data.pl @@ -0,0 +1,822 @@ +#!/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. + +# -*- Mode: perl; indent-tabs-mode: nil -*- + +use strict; +use warnings; + +use Cwd; +use File::Copy::Recursive qw(dircopy); + +my $conf_path; +my $config; + +BEGIN { + print "reading the config file...\n"; + my $conf_file = "selenium_test.conf"; + if (@ARGV) { + $conf_file = shift @ARGV; + } + $config = do "$conf_file" + or die "can't read configuration '$conf_file': $!$@"; + + $conf_path = $config->{bugzilla_path}; +} + +use lib $conf_path; + +use Bugzilla; +use Bugzilla::Attachment; +use Bugzilla::Bug; +use Bugzilla::User; +use Bugzilla::Install; +use Bugzilla::Milestone; +use Bugzilla::Product; +use Bugzilla::Component; +use Bugzilla::Group; +use Bugzilla::Version; +use Bugzilla::Constants; +use Bugzilla::Keyword; +use Bugzilla::Config qw(:admin); +use Bugzilla::User::Setting; +use Bugzilla::Util qw(generate_random_password); + +my $dbh = Bugzilla->dbh; + +# set Bugzilla usage mode to USAGE_MODE_CMDLINE +Bugzilla->usage_mode(USAGE_MODE_CMDLINE); + +########################################################################## +# Set Parameters +########################################################################## + +# Some parameters must be turned on to create bugs requiring them. +# They are also expected to be turned on by some webservice_*.t scripts. +my ($urlbase, $sslbase); +$urlbase = $config->{browser_url} . '/' . $config->{bugzilla_installation}; +$urlbase .= '/' unless $urlbase =~ /\/$/; + +if ($urlbase =~ /^https/) { + $sslbase = $urlbase; + $urlbase =~ s/^https(.+)$/http$1/; +} + +# Create missing priorities +# BMO uses P1-P5 which is different from upstream +my $field = Bugzilla::Field->new({ name => 'priority' }); +foreach my $value (qw(Highest High Normal Low Lowest)) { +# Bugzilla::Field::Choice->type($field)->create({ +# value => $value, +# sortkey => 0 +# }); +} + +# Add missing platforms +$field = Bugzilla::Field->new({ name => 'rep_platform' }); +foreach my $value (qw(PC)) { +# Bugzilla::Field::Choice->type($field)->create({ +# value => $value, +# sortkey => 0 +# }); +} + +my %set_params = ( + urlbase => $urlbase, + sslbase => $sslbase, + usebugaliases => 1, + useqacontact => 1, + mail_delivery_method => 'Test', + maxattachmentsize => 256, + defaultpriority => 'Highest', # BMO CHANGE + timetrackinggroup => 'editbugs', # BMO CHANGE + letsubmitterchoosepriority => 1, # BMO CHANGE + createemailregexp => '.*', # BMO CHANGE +); + +my $params_modified; +foreach my $param (keys %set_params) { + my $value = $set_params{$param}; + next unless defined $value && Bugzilla->params->{$param} ne $value; + SetParam($param, $value); + $params_modified = 1; +} + +write_params() if $params_modified; + +########################################################################## +# Set Default User Preferences +########################################################################## + +# When editing a bug, the page being displayed depends on the +# post_bug_submit_action user pref. We set it globally so that we know +# the exact behavior of process_bug.cgi. +my %user_prefs = (post_bug_submit_action => 'nothing'); + +foreach my $pref (keys %user_prefs) { + my $value = $user_prefs{$pref}; + Bugzilla::User::Setting::set_default($pref, $value, 0); +} + +########################################################################## +# Create Users +########################################################################## +# First of all, remove the default .* regexp for the editbugs group. +my $group = new Bugzilla::Group({ name => 'editbugs' }); +$group->set_user_regexp(''); +$group->update(); + +my @usernames = ( + 'admin', 'no-privs', + 'QA-Selenium-TEST', 'canconfirm', + 'tweakparams', 'permanent_user', + 'editbugs', 'disabled', +); + +print "creating user accounts...\n"; +foreach my $username (@usernames) { + + my $password; + my $login; + my $realname = exists $config->{"$username" . "_user_username"} + ? $config->{"$username" . "_user_username"} + : $username; + + if ($username eq 'permanent_user') { + $password = $config->{admin_user_passwd}; + $login = $config->{$username}; + } + elsif ($username eq 'no-privs') { + $password = $config->{unprivileged_user_passwd}; + $login = $config->{unprivileged_user_login}; + } + elsif ($username eq 'QA-Selenium-TEST') { + $password = $config->{QA_Selenium_TEST_user_passwd}; + $login = $config->{QA_Selenium_TEST_user_login}; + } + else { + $password = $config->{"$username" . "_user_passwd"}; + $login = $config->{"$username" . "_user_login"}; + } + + if ( is_available_username($login) ) { + my %extra_args; + if ($username eq 'disabled') { + $extra_args{disabledtext} = '!!This is the text!!'; + } + + Bugzilla::User->create( + { login_name => $login, + realname => $realname, + cryptpassword => $password, + %extra_args, + } + ); + + if ( $username eq 'admin' or $username eq 'permanent_user' ) { + + Bugzilla::Install::make_admin($login); + } + } +} + +########################################################################## +# Bug statuses +########################################################################## + +# We need to add in the upstream statuses in addition to the BMO ones. + +my @statuses = ( + { + value => undef, + transitions => [['UNCONFIRMED', 0], ['CONFIRMED', 0], ['NEW', 0], + ['ASSIGNED', 0], ['IN_PROGRESS', 0]], + }, + { + value => 'UNCONFIRMED', + sortkey => 100, + isactive => 1, + isopen => 1, + transitions => [['CONFIRMED', 0], ['NEW', 0], ['ASSIGNED', 0], + ['IN_PROGRESS', 0], ['RESOLVED', 0]], + }, + { + value => 'CONFIRMED', + sortkey => 200, + isactive => 1, + isopen => 1, + transitions => [['UNCONFIRMED', 0], ['NEW', 0], ['ASSIGNED', 0], + ['IN_PROGRESS', 0], ['RESOLVED', 0]], + }, + { + value => 'NEW', + sortkey => 300, + isactive => 1, + isopen => 1, + transitions => [['UNCONFIRMED', 0], ['CONFIRMED', 0], ['ASSIGNED', 0], + ['IN_PROGRESS', 0], ['RESOLVED', 0]], + }, + { + value => 'ASSIGNED', + sortkey => 400, + isactive => 1, + isopen => 1, + transitions => [['UNCONFIRMED', 0], ['CONFIRMED', 0], ['NEW', 0], + ['IN_PROGRESS', 0], ['RESOLVED', 0]], + }, + { + value => 'IN_PROGRESS', + sortkey => 500, + isactive => 1, + isopen => 1, + transitions => [['UNCONFIRMED', 0], ['CONFIRMED', 0], ['NEW', 0], + ['ASSIGNED', 0], ['RESOLVED', 0]], + }, + { + value => 'REOPENED', + sortkey => 600, + isactive => 1, + isopen => 1, + transitions => [['UNCONFIRMED', 0], ['CONFIRMED', 0], ['NEW', 0], + ['ASSIGNED', 0], ['IN_PROGRESS', 0], ['RESOLVED', 0]], + }, + { + value => 'RESOLVED', + sortkey => 700, + isactive => 1, + isopen => 0, + transitions => [['UNCONFIRMED', 0], ['CONFIRMED', 0], ['REOPENED', 0], + ['VERIFIED', 0]], + }, + { + value => 'VERIFIED', + sortkey => 800, + isactive => 1, + isopen => 0, + transitions => [['UNCONFIRMED', 0], ['CONFIRMED', 0], ['REOPENED', 0], + ['RESOLVED', 0]], + }, + { + value => 'CLOSED', + sortkey => 900, + isactive => 1, + isopen => 0, + transitions => [['UNCONFIRMED', 0], ['CONFIRMED', 0], ['REOPENED', 0], + ['RESOLVED', 0]], + }, +); + +if ($dbh->selectrow_array("SELECT 1 FROM bug_status WHERE value = 'ASSIGNED'")) { + $dbh->do('DELETE FROM bug_status'); + $dbh->do('DELETE FROM status_workflow'); + + print "creating status workflow...\n"; + + # One pass to add the status entries. + foreach my $status (@statuses) { + next if !$status->{value}; + $dbh->do('INSERT INTO bug_status (value, sortkey, isactive, is_open) VALUES (?, ?, ?, ?)', + undef, ( $status->{value}, $status->{sortkey}, $status->{isactive}, $status->{isopen} )); + } + + # Another pass to add the transitions. + foreach my $status (@statuses) { + my $old_id; + if ($status->{value}) { + my $from_status = new Bugzilla::Status({ name => $status->{value} }); + $old_id = $from_status->{id}; + } else { + $old_id = undef; + } + + foreach my $transition (@{$status->{transitions}}) { + my $to_status = new Bugzilla::Status({ name => $transition->[0] }); + + $dbh->do('INSERT INTO status_workflow (old_status, new_status, require_comment) VALUES (?, ?, ?)', + undef, ( $old_id, $to_status->{id}, $transition->[1] )); + } + } +} + +########################################################################## +# Create Bugs +########################################################################## + +# login to bugzilla +my $admin_user = Bugzilla::User->check($config->{admin_user_login}); +Bugzilla->set_user($admin_user); + +my %field_values = ( + 'priority' => 'Highest', + 'bug_status' => 'CONFIRMED', + 'version' => 'unspecified', + 'bug_file_loc' => '', + 'comment' => 'please ignore this bug', + 'component' => 'TestComponent', + 'rep_platform' => 'All', + 'short_desc' => 'This is a testing bug only', + 'product' => 'TestProduct', + 'op_sys' => 'Linux', + 'bug_severity' => 'normal', + 'groups' => [], +); + +print "creating bugs...\n"; +Bugzilla::Bug->create( \%field_values ); +if (Bugzilla::Bug->new('public_bug')->{error}) { + # The deadline must be set so that this bug can be used to test + # timetracking fields using WebServices. + Bugzilla::Bug->create({ %field_values, alias => 'public_bug', deadline => '2010-01-01' }); +} + +########################################################################## +# Create Classifications +########################################################################## +my @classifications = ({ name => "Class2_QA", + description => "required by Selenium... DON'T DELETE" }, +); + +print "creating classifications...\n"; +foreach my $class (@classifications) { + my $new_class = Bugzilla::Classification->new({ name => $class->{name} }); + if (!$new_class) { + $dbh->do('INSERT INTO classifications (name, description) VALUES (?, ?)', + undef, ( $class->{name}, $class->{description} )); + } +} +########################################################################## +# Create Products +########################################################################## +my $default_platform_id = $dbh->selectcol_arrayref("SELECT id FROM rep_platform WHERE value = 'Unspecified'"); +my $default_op_sys_id = $dbh->selectcol_arrayref("SELECT id FROM op_sys WHERE value = 'Unspecified'"); + +my @products = ( + { product_name => 'QA-Selenium-TEST', + description => "used by Selenium test.. DON'T DELETE", + versions => ['unspecified', 'QAVersion'], + milestones => ['QAMilestone'], + defaultmilestone => '---', + components => [ + { name => "QA-Selenium-TEST", + description => "used by Selenium test.. DON'T DELETE", + initialowner => $config->{QA_Selenium_TEST_user_login}, + initialqacontact => $config->{QA_Selenium_TEST_user_login}, + initial_cc => [$config->{QA_Selenium_TEST_user_login}], + + } + ], + default_platform_id => $default_platform_id, + default_op_sys_id => $default_op_sys_id, + }, + + { product_name => 'Another Product', + description => + "Alternate product used by Selenium. Do not edit!", + versions => ['unspecified', 'Another1', 'Another2'], + milestones => ['AnotherMS1', 'AnotherMS2', 'Milestone'], + defaultmilestone => '---', + + components => [ + { name => "c1", + description => "c1", + initialowner => $config->{permanent_user}, + initialqacontact => '', + initial_cc => [], + + }, + { name => "c2", + description => "c2", + initialowner => $config->{permanent_user}, + initialqacontact => '', + initial_cc => [], + + }, + ], + default_platform_id => $default_platform_id, + default_op_sys_id => $default_op_sys_id, + }, + + { product_name => 'C2 Forever', + description => 'I must remain in the Class2_QA classification ' . + 'in all cases! Do not edit!', + classification => 'Class2_QA', + versions => ['unspecified', 'C2Ver'], + milestones => ['C2Mil'], + defaultmilestone => '---', + components => [ + { name => "Helium", + description => "Feel free to add bugs to me", + initialowner => $config->{permanent_user}, + initialqacontact => '', + initial_cc => [], + + } + ], + default_platform_id => $default_platform_id, + default_op_sys_id => $default_op_sys_id, + }, + + { product_name => 'QA Entry Only', + description => 'Only the QA group may enter bugs here.', + versions => ['unspecified'], + milestones => [], + defaultmilestone => '---', + components => [ + { name => "c1", + description => "Same name as Another Product's component", + initialowner => $config->{QA_Selenium_TEST_user_login}, + initialqacontact => '', + initial_cc => [], + } + ], + default_platform_id => $default_platform_id, + default_op_sys_id => $default_op_sys_id, + }, + + { product_name => 'QA Search Only', + description => 'Only the QA group may search for bugs here.', + versions => ['unspecified'], + milestones => [], + defaultmilestone => '---', + components => [ + { name => "c1", + description => "Still same name as the Another component", + initialowner => $config->{QA_Selenium_TEST_user_login}, + initialqacontact => '', + initial_cc => [], + } + ], + default_platform_id => $default_platform_id, + default_op_sys_id => $default_op_sys_id, + }, +); + +print "creating products...\n"; +foreach my $product (@products) { + my $new_product = + Bugzilla::Product->new({ name => $product->{product_name} }); + if (!$new_product) { + my $class_id = 1; + if ($product->{classification}) { + $class_id = Bugzilla::Classification->new({ name => $product->{classification} })->id; + } + $dbh->do('INSERT INTO products (name, description, classification_id, default_platform_id, default_op_sys_id) + VALUES (?, ?, ?, ?, ?)', + undef, ( $product->{product_name}, $product->{description}, $class_id, + $new_product->{default_platform_id}, $new_product->{default_op_sys_id} )); + + $new_product + = new Bugzilla::Product( { name => $product->{product_name} } ); + + $dbh->do( 'INSERT INTO milestones (product_id, value) VALUES (?, ?)', + undef, ( $new_product->id, $product->{defaultmilestone} ) ); + + # Now clear the internal list of accessible products. + delete Bugzilla->user->{selectable_products}; + + foreach my $component ( @{ $product->{components} } ) { + # BMO Change for ComponentWatching extension + my $watch_user = lc($component->{name}) . '@' . lc($new_product->name) . '.bugs'; + $watch_user =~ s/\s+/\-/g; + + Bugzilla::User->create({ + login_name => $watch_user, + cryptpassword => generate_random_password(), + disable_mail => 1, + }); + + my %params = %{ Bugzilla->input_params }; + $params{watch_user} = $watch_user; + Bugzilla->input_params(\%params); + + Bugzilla::Component->create( + { name => $component->{name}, + product => $new_product, + description => $component->{description}, + initialowner => $component->{initialowner}, + initialqacontact => $component->{initialqacontact}, + initial_cc => $component->{initial_cc}, + } + ); + } + } + + foreach my $version (@{ $product->{versions} }) { + if (!new Bugzilla::Version({ name => $version, + product => $new_product })) + { + Bugzilla::Version->create({value => $version, product => $new_product}); + } + } + + foreach my $milestone (@{ $product->{milestones} }) { + if (!new Bugzilla::Milestone({ name => $milestone, + product => $new_product })) + { + # We don't use Bugzilla::Milestone->create because we want to + # bypass security checks. + $dbh->do('INSERT INTO milestones (product_id, value) VALUES (?,?)', + undef, $new_product->id, $milestone); + } + } +} + +########################################################################## +# Create Groups +########################################################################## +# create Master group +my ( $group_name, $group_desc ) + = ( "Master", "Master Selenium Group DO NOT EDIT!" ); + +print "creating groups...\n"; +if ( !Bugzilla::Group->new( { name => $group_name } ) ) { + my $group = Bugzilla::Group->create({ name => $group_name, + description => $group_desc, + isbuggroup => 1}); + + $dbh->do('INSERT INTO group_control_map + (group_id, product_id, entry, membercontrol, othercontrol, canedit) + SELECT ?, products.id, 0, ?, ?, 0 FROM products', + undef, ( $group->id, CONTROLMAPSHOWN, CONTROLMAPSHOWN ) ); +} + +# create QA-Selenium-TEST group. Do not use Group->create() so that +# the admin group doesn't inherit membership (yes, that's what we want!). +( $group_name, $group_desc ) + = ( "QA-Selenium-TEST", "used by Selenium test.. DON'T DELETE" ); + +if ( !Bugzilla::Group->new( { name => $group_name } ) ) { + $dbh->do('INSERT INTO groups (name, description, isbuggroup, isactive) + VALUES (?, ?, 1, 1)', undef, ( $group_name, $group_desc ) ); +} + +# BMO 'editbugs' is also a member of 'canconfirm' +my $editbugs = Bugzilla::Group->new({ name => 'editbugs' }); +my $canconfirm = Bugzilla::Group->new({ name => 'canconfirm' }); +$dbh->do('INSERT INTO group_group_map VALUES (?, ?, 0)', + undef, $editbugs->id, $canconfirm->id); + +########################################################################## +# Add Users to Groups +########################################################################## +my @users_groups = ( + { user => $config->{QA_Selenium_TEST_user_login}, group => 'QA-Selenium-TEST' }, + { user => $config->{tweakparams_user_login}, group => 'tweakparams' }, + { user => $config->{canconfirm_user_login}, group => 'canconfirm' }, + { user => $config->{editbugs_user_login}, group => 'editbugs' }, +); + +print "adding users to groups...\n"; +foreach my $user_group (@users_groups) { + + my $group = new Bugzilla::Group( { name => $user_group->{group} } ); + my $user = new Bugzilla::User( { name => $user_group->{user} } ); + + my $sth_add_mapping = $dbh->prepare( + qq{INSERT INTO user_group_map (user_id, group_id, isbless, grant_type) + VALUES (?, ?, ?, ?)}); + # Don't crash if the entry already exists. + eval { + $sth_add_mapping->execute( $user->id, $group->id, 0, GRANT_DIRECT ); + }; +} + +########################################################################## +# Associate Products with groups +########################################################################## +# Associate the QA-Selenium-TEST group with the QA-Selenium-TEST. +my $created_group = new Bugzilla::Group( { name => 'QA-Selenium-TEST' } ); +my $secret_product = new Bugzilla::Product( { name => 'QA-Selenium-TEST' } ); +my $no_entry = new Bugzilla::Product({ name => 'QA Entry Only' }); +my $no_search = new Bugzilla::Product({ name => 'QA Search Only' }); + +print "restricting products to groups...\n"; +# Don't crash if the entries already exist. +my $sth = $dbh->prepare('INSERT INTO group_control_map + (group_id, product_id, entry, membercontrol, othercontrol, canedit) + VALUES (?, ?, ?, ?, ?, ?)'); +eval { + $sth->execute($created_group->id, $secret_product->id, 1, CONTROLMAPMANDATORY, + CONTROLMAPMANDATORY, 0); +}; +eval { + $sth->execute($created_group->id, $no_entry->id, 1, CONTROLMAPNA, CONTROLMAPNA, 0); +}; +eval { + $sth->execute($created_group->id, $no_search->id, 0, CONTROLMAPMANDATORY, + CONTROLMAPMANDATORY, 0); +}; + +########################################################################## +# Create flag types +########################################################################## +my @flagtypes = ( + {name => 'spec_multi_flag', desc => 'Specifically requestable and multiplicable bug flag', + is_requestable => 1, is_requesteeble => 1, is_multiplicable => 1, grant_group => 'editbugs', + target_type => 'b', cc_list => '', inclusions => ['Another Product:c1']}, +); + +print "creating flag types...\n"; +foreach my $flag (@flagtypes) { + # The name is not unique, even within a single product/component, so there is NO WAY + # to know if the existing flag type is the one we want or not. + # As our Selenium scripts would be confused anyway if there is already such a flag name, + # we simply skip it and assume the existing flag type is the one we want. + next if new Bugzilla::FlagType({ name => $flag->{name} }); + + my $grant_group_id = $flag->{grant_group} ? Bugzilla::Group->new({ name => $flag->{grant_group} })->id : undef; + my $request_group_id = $flag->{request_group} ? Bugzilla::Group->new({ name => $flag->{request_group} })->id : undef; + + $dbh->do('INSERT INTO flagtypes (name, description, cc_list, target_type, is_requestable, + is_requesteeble, is_multiplicable, grant_group_id, request_group_id) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)', + undef, ($flag->{name}, $flag->{desc}, $flag->{cc_list}, $flag->{target_type}, + $flag->{is_requestable}, $flag->{is_requesteeble}, $flag->{is_multiplicable}, + $grant_group_id, $request_group_id)); + + my $type_id = $dbh->bz_last_key('flagtypes', 'id'); + + foreach my $inclusion (@{$flag->{inclusions}}) { + my ($product, $component) = split(':', $inclusion); + my ($prod_id, $comp_id); + if ($product) { + my $prod_obj = Bugzilla::Product->new({ name => $product }); + $prod_id = $prod_obj->id; + if ($component) { + $comp_id = Bugzilla::Component->new({ name => $component, product => $prod_obj})->id; + } + } + $dbh->do('INSERT INTO flaginclusions (type_id, product_id, component_id) + VALUES (?, ?, ?)', + undef, ($type_id, $prod_id, $comp_id)); + } +} + +########################################################################## +# Create custom fields +########################################################################## +my @fields = ( + { name => 'cf_QA_status', + description => 'QA Status', + type => FIELD_TYPE_MULTI_SELECT, + sortkey => 100, + mailhead => 0, + enter_bug => 1, + obsolete => 0, + custom => 1, + values => ['verified', 'in progress', 'untested'] + }, + { name => 'cf_single_select', + description => 'SingSel', + type => FIELD_TYPE_SINGLE_SELECT, + sortkey => 200, + mailhead => 0, + enter_bug => 1, + custom => 1, + obsolete => 0, + values => [qw(one two three)], + }, +); + +print "creating custom fields...\n"; +foreach my $f (@fields) { + # Skip existing custom fields. + next if Bugzilla::Field->new({ name => $f->{name} }); + + my @values; + if (exists $f->{values}) { + @values = @{$f->{values}}; + # We have to delete this key, else create() will complain + # that 'values' is not an existing column name. + delete $f->{values}; + } + Bugzilla::Field->create($f); + my $field = Bugzilla::Field->new({ name => $f->{name} }); + + # Now populate the table with valid values, if necessary. + next unless scalar @values; + + my $sth = $dbh->prepare('INSERT INTO ' . $field->name . ' (value) VALUES (?)'); + foreach my $value (@values) { + $sth->execute($value); + } +} + +#################################################################### +# Set Parameters That Require Other Things To Have Been Done First # +#################################################################### + +if (Bugzilla->params->{insidergroup} ne 'QA-Selenium-TEST') { + SetParam('insidergroup', 'QA-Selenium-TEST'); + $params_modified = 1; +} + +if ($params_modified) { + write_params(); + print <check($config->{QA_Selenium_TEST_user_login}); +Bugzilla->set_user($test_user); + +print "Creating private bug(s)...\n"; +if (Bugzilla::Bug->new('private_bug')->{error}) { + my %priv_values = %field_values; + $priv_values{alias} = 'private_bug'; + $priv_values{product} = 'QA-Selenium-TEST'; + $priv_values{component} = 'QA-Selenium-TEST'; + my $bug = Bugzilla::Bug->create(\%priv_values); +} + +###################### +# Create Attachments # +###################### + +# BMO FIXME: Users must be in 'editbugs' to set their own +# content type other than text/plain or application/octet-stream +$group = new Bugzilla::Group( { name => 'editbugs' } ); +my $sth_add_mapping = $dbh->prepare( + qq{INSERT INTO user_group_map (user_id, group_id, isbless, grant_type) + VALUES (?, ?, ?, ?)}); +# Don't crash if the entry already exists. +eval { + $sth_add_mapping->execute( Bugzilla->user->id, $group->id, 0, GRANT_DIRECT ); +}; + +print "creating attachments...\n"; + +# We use the contents of this script as the attachment. +open(my $attachment_fh, '<', __FILE__) or die __FILE__ . ": $!"; + +my $attachment_contents; +{ local $/; $attachment_contents = <$attachment_fh>; } + +close($attachment_fh); + +foreach my $alias (qw(public_bug private_bug)) { + my $bug = Bugzilla::Bug->new($alias); + foreach my $is_private (0, 1) { + Bugzilla::Attachment->create({ + bug => $bug, + data => $attachment_contents, + description => "${alias}_${is_private}", + filename => "${alias}_${is_private}.pl", + mimetype => 'application/x-perl', + isprivate => $is_private, + }); + } +} + +# BMO FIXME: Remove test user from 'editbugs' group +my $sth_remove_mapping = $dbh->prepare( + qq{DELETE FROM user_group_map WHERE user_id = ? + AND group_id = ? AND isbless = 0 AND grant_type = ?}); +# Don't crash if the entry already exists. +eval { + $sth_remove_mapping->execute( Bugzilla->user->id, $group->id, GRANT_DIRECT ); +}; + +################### +# Create Keywords # +################### + +my @keywords = ( + { name => 'test-keyword-1', + description => 'Created for Bugzilla QA Tests, Keyword 1' }, + { name => 'test-keyword-2', + description => 'Created for Bugzilla QA Tests, Keyword 2' }, +); + +print "creating keywords...\n"; +foreach my $kw (@keywords) { + next if new Bugzilla::Keyword({ name => $kw->{name} }); + Bugzilla::Keyword->create($kw); +} + +############################ +# Install the QA extension # +############################ + +print "copying the QA extension...\n"; +dircopy("$conf_path/qa/extensions/QA", "$conf_path/extensions/QA"); + +my $cwd = cwd(); +chdir($conf_path); +system("perl", "contrib/fixperms.pl"); +chdir($cwd); + +print "installation and configuration complete!\n"; diff --git a/qa/config/patch.diff b/qa/config/patch.diff new file mode 100644 index 000000000..d85ecbdfe --- /dev/null +++ b/qa/config/patch.diff @@ -0,0 +1,18 @@ +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 + }, diff --git a/qa/config/selenium_test.conf b/qa/config/selenium_test.conf new file mode 100644 index 000000000..896d332e9 --- /dev/null +++ b/qa/config/selenium_test.conf @@ -0,0 +1,49 @@ +# 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 @mozilla.test by something more relevant to you, +# also what comes before @mozilla.test 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/1144485/qa/config/patch.diff', + 'bugzilla_installation' => '1144485', + 'bugzilla_path' => '/home/bugzilla/devel/htdocs/1144485', + 'test_bug_1' => 1, + 'test_bug_2' => 2, + 'admin_user_login' => 'admin@mozilla.test', + 'admin_user_passwd' => 'password', + 'admin_user_username' => 'QA Admin', + 'admin_user_nick' => 'admin', + 'permanent_user' => 'permanent_user@mozilla.test', + 'permanent_user_login' => 'permanent_user@mozilla.test', + 'permanent_user_passwd' => 'password', + 'unprivileged_user_login' => 'no-privs@mozilla.test', + 'unprivileged_user_passwd' => 'password', + 'unprivileged_user_username' => 'no-privs', + 'unprivileged_user_nick' => 'no-privs', + 'unprivileged_user_login_truncated' => 'no-privs@mo', + 'QA_Selenium_TEST_user_login' => 'QA-Selenium-TEST@mozilla.test', + 'QA_Selenium_TEST_user_passwd' => 'password', + 'editbugs_user_login' => 'editbugs@mozilla.test', + 'editbugs_user_passwd' => 'password', + 'canconfirm_user_login' => 'canconfirm@mozilla.test', + 'canconfirm_user_passwd' => 'password', + 'tweakparams_user_login' => 'tweakparams@mozilla.test', + 'tweakparams_user_login_truncated' => 'tweakparams@mo', + 'tweakparams_user_passwd' => 'password', + 'disabled_user_login' => 'disabled@mozilla.test', + 'disabled_user_passwd' => 'password', + 'common_email' => '@mozilla.test', + 'test_extensions' => 1, +}; diff --git a/qa/extensions/QA/Config.pm b/qa/extensions/QA/Config.pm new file mode 100644 index 000000000..59799ec6b --- /dev/null +++ b/qa/extensions/QA/Config.pm @@ -0,0 +1,20 @@ +# 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 strict; + +use constant NAME => 'QA'; + +use constant REQUIRED_MODULES => [ +]; + +use constant OPTIONAL_MODULES => [ +]; + +__PACKAGE__->NAME; diff --git a/qa/extensions/QA/Extension.pm b/qa/extensions/QA/Extension.pm new file mode 100644 index 000000000..b5f404d74 --- /dev/null +++ b/qa/extensions/QA/Extension.pm @@ -0,0 +1,71 @@ +# 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 strict; +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; diff --git a/qa/extensions/QA/lib/Util.pm b/qa/extensions/QA/lib/Util.pm new file mode 100644 index 000000000..9bc2d8dbb --- /dev/null +++ b/qa/extensions/QA/lib/Util.pm @@ -0,0 +1,25 @@ +# 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 strict; +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; diff --git a/qa/extensions/QA/template/en/default/pages/qa/email_in.html.tmpl b/qa/extensions/QA/template/en/default/pages/qa/email_in.html.tmpl new file mode 100644 index 000000000..bcb75107d --- /dev/null +++ b/qa/extensions/QA/template/en/default/pages/qa/email_in.html.tmpl @@ -0,0 +1,7 @@ +[%# 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. + #%] diff --git a/qa/extensions/QA/template/en/default/qa/create_bug.txt.tmpl b/qa/extensions/QA/template/en/default/qa/create_bug.txt.tmpl new file mode 100644 index 000000000..5a83a6c5b --- /dev/null +++ b/qa/extensions/QA/template/en/default/qa/create_bug.txt.tmpl @@ -0,0 +1,17 @@ +[%# 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 %]). diff --git a/qa/extensions/QA/template/en/default/qa/create_bug_with_headers.txt.tmpl b/qa/extensions/QA/template/en/default/qa/create_bug_with_headers.txt.tmpl new file mode 100644 index 000000000..997378343 --- /dev/null +++ b/qa/extensions/QA/template/en/default/qa/create_bug_with_headers.txt.tmpl @@ -0,0 +1,33 @@ +[%# 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: +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. diff --git a/qa/extensions/QA/template/en/default/qa/results.html.tmpl b/qa/extensions/QA/template/en/default/qa/results.html.tmpl new file mode 100644 index 000000000..a2f812697 --- /dev/null +++ b/qa/extensions/QA/template/en/default/qa/results.html.tmpl @@ -0,0 +1,28 @@ +[%# 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 %] + +

Action '[% action FILTER html %]' successful

+ +
+

PID: [% pid FILTER html %]

+

[%+ terms.Bug %] ID: [% bug_id FILTER html %]

+ +

Full output:

+
[% output FILTER html_light %]
+ +[% PROCESS global/footer.html.tmpl %] diff --git a/qa/extensions/QA/template/en/default/qa/update_bug.txt.tmpl b/qa/extensions/QA/template/en/default/qa/update_bug.txt.tmpl new file mode 100644 index 000000000..f37c00262 --- /dev/null +++ b/qa/extensions/QA/template/en/default/qa/update_bug.txt.tmpl @@ -0,0 +1,13 @@ +[%# 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. diff --git a/qa/extensions/QA/template/en/default/qa/update_bug_with_headers.txt.tmpl b/qa/extensions/QA/template/en/default/qa/update_bug_with_headers.txt.tmpl new file mode 100644 index 000000000..fd093d3b0 --- /dev/null +++ b/qa/extensions/QA/template/en/default/qa/update_bug_with_headers.txt.tmpl @@ -0,0 +1,29 @@ +[%# 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: +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. diff --git a/qa/t/lib/QA/RPC.pm b/qa/t/lib/QA/RPC.pm new file mode 100644 index 000000000..4053c4dfe --- /dev/null +++ b/qa/t/lib/QA/RPC.pm @@ -0,0 +1,284 @@ +# 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 strict; +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 , 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->{alias} = random_string(40); + $public_bug->{whiteboard} = join(' ', @whiteboard_strings); + $public_bug->{summary} = join(' ', @summary_strings); + + my $private_bug = dclone($public_bug); + $private_bug->{alias} = random_string(40); + 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__ diff --git a/qa/t/lib/QA/RPC/JSONRPC.pm b/qa/t/lib/QA/RPC/JSONRPC.pm new file mode 100644 index 000000000..4175b10fc --- /dev/null +++ b/qa/t/lib/QA/RPC/JSONRPC.pm @@ -0,0 +1,168 @@ +# 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 strict; + +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 .= "¶ms=$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'}; +} diff --git a/qa/t/lib/QA/RPC/XMLRPC.pm b/qa/t/lib/QA/RPC/XMLRPC.pm new file mode 100644 index 000000000..d88d4092e --- /dev/null +++ b/qa/t/lib/QA/RPC/XMLRPC.pm @@ -0,0 +1,19 @@ +# 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 strict; +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__ diff --git a/qa/t/lib/QA/Tests.pm b/qa/t/lib/QA/Tests.pm new file mode 100644 index 000000000..0bd0942fa --- /dev/null +++ b/qa/t/lib/QA/Tests.pm @@ -0,0 +1,108 @@ +# 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 strict; +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; diff --git a/qa/t/lib/QA/Util.pm b/qa/t/lib/QA/Util.pm new file mode 100644 index 000000000..d8d8ae52f --- /dev/null +++ b/qa/t/lib/QA/Util.pm @@ -0,0 +1,375 @@ +# 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::Util; + +use strict; +use Data::Dumper; +use Test::More; +use Test::WWW::Selenium; +use WWW::Selenium::Util qw(server_is_running); + +# Fixes wide character warnings +BEGIN { + my $builder = Test::More->builder; + binmode $builder->output, ":encoding(utf8)"; + binmode $builder->failure_output, ":encoding(utf8)"; + binmode $builder->todo_output, ":encoding(utf8)"; +} + +use base qw(Exporter); +@QA::Util::EXPORT = qw( + trim + url_quote + random_string + + log_in + logout + file_bug_in_product + create_bug + edit_bug + edit_bug_and_return + go_to_bug + go_to_home + go_to_admin + edit_product + add_product + open_advanced_search_page + set_parameters + + get_selenium + get_rpc_clients + + WAIT_TIME + CHROME_MODE +); + +# How long we wait for pages to load. +use constant WAIT_TIME => 60000; +use constant CONF_FILE => "../config/selenium_test.conf"; +use constant CHROME_MODE => 1; +use constant NDASH => chr(0x2013); + +##################### +# Utility Functions # +##################### + +sub random_string { + my $size = shift || 30; # default to 30 chars if nothing specified + return join("", map{ ('0'..'9','a'..'z','A'..'Z')[rand 62] } (1..$size)); +} + +# Remove consecutive as well as leading and trailing whitespaces. +sub trim { + my ($str) = @_; + if ($str) { + $str =~ s/[\r\n\t\s]+/ /g; + $str =~ s/^\s+//g; + $str =~ s/\s+$//g; + } + return $str; +} + +# This originally came from CGI.pm, by Lincoln D. Stein +sub url_quote { + my ($toencode) = (@_); + $toencode =~ s/([^a-zA-Z0-9_\-.])/uc sprintf("%%%02x",ord($1))/eg; + return $toencode; +} + +################### +# Setup Functions # +################### + +sub get_config { + # read the test configuration file + my $conf_file = CONF_FILE; + my $config = do($conf_file) + or die "can't read configuration '$conf_file': $!$@"; +} + +sub get_selenium { + my $chrome_mode = shift; + my $config = get_config(); + + if (!server_is_running) { + die "Selenium Server isn't running!"; + } + + my $sel = Test::WWW::Selenium->new( + host => $config->{host}, + port => $config->{port}, + browser => $chrome_mode ? $config->{experimental_browser_launcher} : $config->{browser}, + browser_url => $config->{browser_url} + ); + + return ($sel, $config); +} + +sub get_xmlrpc_client { + my $config = get_config(); + my $xmlrpc_url = $config->{browser_url} . "/" . + $config->{bugzilla_installation} . "/xmlrpc.cgi"; + + require QA::RPC::XMLRPC; + my $rpc = new QA::RPC::XMLRPC(proxy => $xmlrpc_url); + return ($rpc, $config); +} + +sub get_jsonrpc_client { + my ($get_mode) = @_; + require QA::RPC::JSONRPC; + my $rpc = new QA::RPC::JSONRPC(); + # If we don't set a long timeout, then the Bug.add_comment test + # where we add a too-large comment fails. + $rpc->transport->timeout(180); + $rpc->version($get_mode ? '1.1' : '1.0'); + $rpc->bz_get_mode($get_mode); + return $rpc; +} + +sub get_rpc_clients { + my ($xmlrpc, $config) = get_xmlrpc_client(); + my $jsonrpc = get_jsonrpc_client(); + my $jsonrpc_get = get_jsonrpc_client('GET'); + return ($config, $xmlrpc, $jsonrpc, $jsonrpc_get); +} + +################################ +# Helpers for Selenium Scripts # +################################ + +sub go_to_home { + my ($sel, $config) = @_; + $sel->open_ok("/$config->{bugzilla_installation}/", undef, "Go to the home page"); + $sel->title_is("Bugzilla Main Page"); +} + +# Go to the home/login page and log in. +sub log_in { + my ($sel, $config, $user) = @_; + + go_to_home($sel, $config); + $sel->type_ok("Bugzilla_login_top", $config->{"${user}_user_login"}, "Enter $user login name"); + $sel->type_ok("Bugzilla_password_top", $config->{"${user}_user_passwd"}, "Enter $user password"); + $sel->click_ok("log_in_top", undef, "Submit credentials"); + $sel->wait_for_page_to_load(WAIT_TIME); + $sel->title_is("Bugzilla Main Page", "User is logged in"); +} + +# Log out. Will fail if you are not logged in. +sub logout { + my $sel = shift; + + $sel->click_ok("link=Log out", undef, "Logout"); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->title_is("Logged Out"); +} + +# Display the bug form to enter a bug in the given product. +sub file_bug_in_product { + my ($sel, $product, $classification) = @_; + + $classification ||= "Unclassified"; + $sel->click_ok("link=New", undef, "Go create a new bug"); + $sel->wait_for_page_to_load(WAIT_TIME); + my $title = $sel->get_title(); + if ($sel->is_text_present("Select Classification")) { + ok(1, "More than one enterable classification available. Display them in a list"); + $sel->click_ok("link=$classification", undef, "Choose $classification"); + $sel->wait_for_page_to_load(WAIT_TIME); + $title = $sel->get_title(); + } + if ($sel->is_text_present("Which product is affected by the problem")) { + ok(1, "Which product is affected by the problem"); + $sel->click_ok("link=Other Products", undef, "Choose full product list"); + $sel->wait_for_page_to_load(WAIT_TIME); + $title = $sel->get_title(); + } + if ($sel->is_text_present($product)) { + ok(1, "Display the list of enterable products"); + $sel->open_ok("/bmo/enter_bug.cgi?product=$product&format=__default__", undef, "Choose product $product"); + $sel->wait_for_page_to_load(WAIT_TIME); + } + else { + ok(1, "Only one product available in $classification. Skipping the 'Choose product' page.") + } + $sel->title_is("Enter Bug: $product", "Display form to enter bug data"); + # Always make sure all fields are visible + if ($sel->is_element_present('//input[@value="Show Advanced Fields"]')) { + $sel->click_ok('//input[@value="Show Advanced Fields"]'); + } +} + +sub create_bug { + my ($sel, $bug_summary) = @_; + my $ndash = NDASH; + + $sel->click_ok('commit'); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + my $bug_id = $sel->get_value('//input[@name="id" and @type="hidden"]'); + $sel->title_like(qr/$bug_id $ndash( \(.*\))? $bug_summary/, "Bug $bug_id created with summary '$bug_summary'"); + return $bug_id; +} + +sub edit_bug { + my ($sel, $bug_id, $bug_summary, $options) = @_; + my $btn_id = $options ? $options->{id} : 'commit'; + $sel->click_ok($btn_id); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->is_text_present_ok("Changes submitted for bug $bug_id"); +} + +sub edit_bug_and_return { + my ($sel, $bug_id, $bug_summary, $options) = @_; + my $ndash = NDASH; + edit_bug($sel, $bug_id, $bug_summary, $options); + $sel->click_ok("//a[contains(\@href, 'show_bug.cgi?id=$bug_id')]"); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->title_is("$bug_id $ndash $bug_summary", "Returning back to bug $bug_id"); +} + +# Go to show_bug.cgi. +sub go_to_bug { + my ($sel, $bug_id) = @_; + + $sel->type_ok("quicksearch_top", $bug_id); + $sel->click_ok("find_top", undef, "Go to bug $bug_id"); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + my $bug_title = $sel->get_title(); + utf8::encode($bug_title) if utf8::is_utf8($bug_title); + $sel->title_like(qr/^$bug_id /, $bug_title); +} + +# Go to admin.cgi. +sub go_to_admin { + my $sel = shift; + + $sel->click_ok("link=Administration", undef, "Go to the Admin page"); + $sel->wait_for_page_to_load(WAIT_TIME); + $sel->title_like(qr/^Administer your installation/, "Display admin.cgi"); +} + +# Go to editproducts.cgi and display the given product. +sub edit_product { + my ($sel, $product, $classification) = @_; + + $classification ||= "Unclassified"; + go_to_admin($sel); + $sel->click_ok("link=Products", undef, "Go to the Products page"); + $sel->wait_for_page_to_load(WAIT_TIME); + my $title = $sel->get_title(); + if ($title eq "Select Classification") { + ok(1, "More than one enterable classification available. Display them in a list"); + $sel->click_ok("link=$classification", undef, "Choose $classification"); + $sel->wait_for_page_to_load(WAIT_TIME); + } + else { + $sel->title_is("Select product", "Display the list of enterable products"); + } + $sel->click_ok("link=$product", undef, "Choose $product"); + $sel->wait_for_page_to_load(WAIT_TIME); + $sel->title_is("Edit Product '$product'", "Display properties of $product"); +} + +sub add_product { + my ($sel, $classification) = @_; + + $classification ||= "Unclassified"; + go_to_admin($sel); + $sel->click_ok("link=Products", undef, "Go to the Products page"); + $sel->wait_for_page_to_load(WAIT_TIME); + my $title = $sel->get_title(); + if ($title eq "Select Classification") { + ok(1, "More than one enterable classification available. Display them in a list"); + $sel->click_ok("//a[contains(\@href, 'editproducts.cgi?action=add&classification=$classification')]", + undef, "Add product to $classification"); + } + else { + $sel->title_is("Select product", "Display the list of enterable products"); + $sel->click_ok("link=Add", undef, "Add a new product"); + } + $sel->wait_for_page_to_load(WAIT_TIME); + $sel->title_is("Add Product", "Display the new product form"); +} + +sub open_advanced_search_page { + my $sel = shift; + + $sel->click_ok("link=Search"); + $sel->wait_for_page_to_load(WAIT_TIME); + my $title = $sel->get_title(); + if ($title eq "Simple Search") { + ok(1, "Display the simple search form"); + $sel->click_ok("link=Advanced Search"); + $sel->wait_for_page_to_load(WAIT_TIME); + } + $sel->title_is("Search for bugs", "Display the Advanced search form"); +} + +# $params is a hashref of the form: +# {section1 => { param1 => {type => '(text|select)', value => 'foo'}, +# param2 => {type => '(text|select)', value => 'bar'}, +# param3 => undef }, +# section2 => { param4 => ...}, +# } +# section1, section2, ... is the name of the section +# param1, param2, ... is the name of the parameter (which must belong to the given section) +# type => 'text' is for text fields +# type => 'select' is for drop-down select fields +# undef is for radio buttons (in which case the parameter must be the ID of the radio button) +# value => 'foo' is the value of the parameter (either text or label) +sub set_parameters { + my ($sel, $params) = @_; + + go_to_admin($sel); + $sel->click_ok("link=Parameters", undef, "Go to the Config Parameters page"); + $sel->wait_for_page_to_load(WAIT_TIME); + $sel->title_is("Configuration: Required Settings"); + my $last_section = "Required Settings"; + + foreach my $section (keys %$params) { + if ($section ne $last_section) { + $sel->click_ok("link=$section"); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->title_is("Configuration: $section"); + $last_section = $section; + } + my $param_list = $params->{$section}; + foreach my $param (keys %$param_list) { + my $data = $param_list->{$param}; + if (defined $data) { + my $type = $data->{type}; + my $value = $data->{value}; + + if ($type eq 'text') { + $sel->type_ok($param, $value); + } + elsif ($type eq 'select') { + $sel->select_ok($param, "label=$value"); + } + else { + ok(0, "Unknown parameter type: $type"); + } + } + else { + # If the value is undefined, then the param name is + # the ID of the radio button. + $sel->click_ok($param); + } + } + $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"); + } +} + +1; + +__END__ diff --git a/qa/t/selenium_server_start.t b/qa/t/selenium_server_start.t new file mode 100644 index 000000000..c08db293c --- /dev/null +++ b/qa/t/selenium_server_start.t @@ -0,0 +1,83 @@ +# 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 strict; +use warnings; + +use constant DISPLAY => 99; +#use constant DISPLAY => 0; + +use Test::More tests => 12; +#use Test::More tests => 4; + +my $pid; + +# Start the Xvfb server first +$pid = xserver_start(); +ok($pid, "X Server started with PID $pid on display " . DISPLAY); +ok(open(XPID, ">testing.x.pid"), "Opening testing.x.pid"); +ok((print XPID $pid), "Writing testing.x.pid"); +ok(close(XPID), "Closing testing.x.pid"); + +# Start the VNC service second +ok($pid = vnc_start(), "VNC desktop started with PID $pid"); +ok(open(VNCPID, ">testing.vnc.pid"), "Opening testing.vnc.pid"); +ok((print VNCPID $pid), "Writing testing.vnc.pid"); +ok(close(VNCPID), "Closing testing.vnc.pid"); + +# Start the selenium server third +ok($pid = selenium_start(), "Selenium RC server started with PID $pid"); +ok(open(SPID, ">testing.selenium.pid"), "Opening testing.selenium.pid"); +ok((print SPID $pid), "Writing testing.selenium.pid"); +ok(close(SPID), "Closing testing.selenium.pid"); + +sleep(10); + +# Subroutines + +sub xserver_start { + my $pid; + my @x_cmd = qw(Xvfb -ac -screen 0 1600x1200x24 -fbdir /tmp); + push(@x_cmd, ":" . DISPLAY); + $pid = fork(); + if (!$pid) { + open(STDOUT, ">/dev/null"); + open(STDERR, ">/dev/null"); + exec(@x_cmd) || die "unable to execute: $!"; + } + else { + return $pid; + } + return 0; +} + +sub vnc_start { + my @vnc_cmd = qw(x11vnc -viewonly -forever -nopw -quiet -display); + push(@vnc_cmd, ":" . DISPLAY); + my $pid = fork(); + if (!$pid) { + open(STDOUT, ">/dev/null"); + open(STDERR, ">/dev/null"); + exec(@vnc_cmd) || die "unabled to execute: $!"; + } + return $pid; +} + +sub selenium_start { + my @selenium_cmd = qw(java -jar ../config/selenium-server-standalone.jar + -firefoxProfileTemplate ../config/firefox + -log ../config/selenium.log + -singlewindow); + unshift(@selenium_cmd, "env", "DISPLAY=:" . DISPLAY); + my $pid = fork(); + if (!$pid) { + open(STDOUT, ">/dev/null"); + open(STDERR, ">/dev/null"); + exec(@selenium_cmd) || die "unable to execute: $!"; + } + return $pid; +} diff --git a/qa/t/selenium_server_stop.t b/qa/t/selenium_server_stop.t new file mode 100644 index 000000000..62a29f38c --- /dev/null +++ b/qa/t/selenium_server_stop.t @@ -0,0 +1,34 @@ +# 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 strict; +use warnings; + +use Test::More tests => 15; + +my $pid; + +# Stop the selenium server first +ok(open(SPID, "), "Reading testing.selenium.pid"); +ok(close(SPID), "Closing testing.selenium.pid"); +ok(kill(9, $pid), "Killing process $pid"); +ok(unlink("testing.selenium.pid"), "Removing testing.selenium.pid"); + +# Stop the VNC service second +ok(open(VNCPID, "), "Reading testing.vnc.pid"); +ok(close(VNCPID), "Closing testing.vnc.pid"); +ok(kill(9, $pid), "Killing process $pid"); +ok(unlink("testing.vnc.pid"), "Removing testing.vnc.pid"); + +# Stop the Xvfb server third +ok(open(XPID, "), "Reading testing.x.pid"); +ok(close(XPID), "Closing testing.x.pid"); +ok(kill(9, $pid), "Killing process $pid"); +ok(unlink("testing.x.pid"), "Removing testing.x.pid"); diff --git a/qa/t/test_bmo_autolinkification.t b/qa/t/test_bmo_autolinkification.t new file mode 100644 index 000000000..520301165 --- /dev/null +++ b/qa/t/test_bmo_autolinkification.t @@ -0,0 +1,53 @@ +# 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 strict; +use warnings; +use lib qw(lib); + +use Test::More "no_plan"; + +use QA::Util; + +my ($sel, $config) = get_selenium(); + +log_in($sel, $config, 'unprivileged'); +file_bug_in_product($sel, 'TestProduct'); +my $bug_summary = "linkification test bug"; +$sel->type_ok("short_desc", $bug_summary); +$sel->type_ok("comment", "linkification test"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_like(qr/\d+ \S $bug_summary/, "Bug created"); +my $bug_id = $sel->get_value("//input[\@name='id' and \@type='hidden']"); + +$sel->type_ok("comment", "bp-63f096f7-253b-4ee2-ae3d-8bb782090824"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_like(qr/\d+ \S $bug_summary/, "crash report added"); +$sel->click_ok("link=bug $bug_id"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->attribute_is('link=bp-63f096f7-253b-4ee2-ae3d-8bb782090824@href', 'https://crash-stats.mozilla.com/report/index/63f096f7-253b-4ee2-ae3d-8bb782090824'); + +$sel->type_ok("comment", "CVE-2010-2884"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_like(qr/\d+ \S $bug_summary/, "cve added"); +$sel->click_ok("link=bug $bug_id"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->attribute_is('link=CVE-2010-2884@href', 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-2884'); + +$sel->type_ok("comment", "r12345"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_like(qr/\d+ \S $bug_summary/, "svn revision added"); +$sel->click_ok("link=bug $bug_id"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->attribute_is('link=r12345@href', 'https://viewvc.svn.mozilla.org/vc?view=rev&revision=12345'); + +logout($sel); + diff --git a/qa/t/test_bmo_enter_new_bug.t b/qa/t/test_bmo_enter_new_bug.t new file mode 100644 index 000000000..ac4a9ca8b --- /dev/null +++ b/qa/t/test_bmo_enter_new_bug.t @@ -0,0 +1,421 @@ +# 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. + +# Comments: +# 1. Some of the forms have been commented as they have been removed since +# this script was originally created. I left them in insteading of deleting +# so they could be used for reference for adding new form tests. +# 2. The _check_* utility functions for creating objects should be moved to +# generate_test_data.pl at some point. + +use strict; +use warnings; +use lib qw(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-off" => undef} }); + +# mktgevent and swag are dependent so we create the mktgevent bug first so +# we can provide the bug id to swag + +## mktgevent +# +#_check_product('Marketing'); +#_check_component('Marketing', 'Event Requests'); +#_check_component('Marketing', 'Swag Requests'); +#_check_group('mozilla-corporation-confidential'); +# +## FIXME figure out how to use format= with file_bug_in_product +# +#$sel->open_ok("/$config->{bugzilla_installation}/enter_bug.cgi?product=Marketing&format=mktgevent"); +#$sel->wait_for_page_to_load_ok(WAIT_TIME); +#$sel->title_is("Event Request Form", "Open custom bug entry form - mktgevent"); +#$sel->type_ok("firstname", "Bugzilla", "Enter first name"); +#$sel->type_ok("lastname", "Administrator", "Enter last name"); +#$sel->type_ok("email", $config->{'admin_user_login'}, "Enter email address"); +#$sel->type_ok("eventname", "Event Name", "Enter event name"); +#$sel->type_ok("website", $config->{'browser_url'}, "Enter web site"); +#$sel->type_ok("goals", "Goals for the event", "Enter goals"); +#$sel->type_ok("date", "2032/01/01", "Enter date"); +#$sel->type_ok("successmeasure", "Success Measure", "Enter measure of success"); +#$sel->click_ok("doing", "value=Other", "Select what doing"); +#$sel->type_ok("doing-other-what", "What will you be doing at the event", "Enter other what doing"); +#$sel->select_ok("attendees", "value=1-99", "Select number of attendees"); +#$sel->select_ok("audience", "value=Contributors", "Select targeted audience"); +#$sel->click_ok("commit", undef, "Submit bug data to post_bug.cgi"); +#$sel->wait_for_page_to_load_ok(WAIT_TIME); +#$sel->is_text_present_ok('has been added to the database', 'Bug created'); +#my $mktgevent_bug_id = $sel->get_value('//input[@name="id" and @type="hidden"]'); +# +## swag +# +#$sel->open_ok("/$config->{bugzilla_installation}/enter_bug.cgi?product=Marketing&format=swag"); +#$sel->wait_for_page_to_load_ok(WAIT_TIME); +#$sel->title_is("Swag Request Form", "Open custom bug entry form - swag"); +#$sel->type_ok("firstname", "Bugzilla", "Enter first name"); +#$sel->type_ok("lastname", "Administrator", "Enter last name"); +#$sel->type_ok("dependson", $mktgevent_bug_id, "Enter event request bug id"); +#$sel->type_ok("email", $config->{'admin_user_login'}, "Enter email address"); +#$sel->type_ok("cc", $config->{'unprivileged_user_login'}, "Enter cc address"); +#$sel->type_ok("additional", "Specific swag needed", "Enter specific swag needed"); +#$sel->type_ok("shiptofirstname", "Bugzilla", "Enter ship to first name"); +#$sel->type_ok("shiptolastname", "Administrator", "Enter ship to last name"); +#$sel->type_ok("shiptoaddress", "100 Some Street", "Enter ship to address"); +#$sel->type_ok("shiptoaddress2", "Suite 200", "Enter ship to address 2"); +#$sel->type_ok("shiptocity", "Mountain View", "Enter ship to city"); +#$sel->type_ok("shiptostate", "California", "Enter ship to state"); +#$sel->type_ok("shiptocountry", "USA", "Enter ship to country"); +#$sel->type_ok("shiptopcode", "94041", "Enter ship to postal code"); +#$sel->type_ok("shiptophone", "1-800-555-1212", "Enter ship to phone"); +#$sel->type_ok("shiptoidrut", "What is this?", "Enter ship to personal id/rut"); +#$sel->type_ok("comment", "--- Bug created by Selenium ---", "Enter bug description"); +#$sel->click_ok("commit", undef, "Submit bug data to post_bug.cgi"); +#$sel->wait_for_page_to_load_ok(WAIT_TIME); +#$sel->is_text_present_ok('has been added to the database', 'Bug created'); +#my $swag_bug_id = $sel->get_value('//input[@name="id" and @type="hidden"]'); + +# trademark + +_check_product('Marketing'); +_check_component('Marketing', 'Trademark Permissions'); +_check_group('marketing-private'); + +$sel->open_ok("/$config->{bugzilla_installation}/enter_bug.cgi?product=Marketing&format=trademark"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Trademark Usage Requests", "Open custom bug entry form - trademark"); +$sel->type_ok("short_desc", "Bug created by Selenium", "Enter bug summary"); +$sel->type_ok("comment", "--- Bug created by Selenium ---", "Enter bug description"); +$sel->click_ok("commit", undef, "Submit bug data to post_bug.cgi"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->is_text_present_ok('has been added to the database', 'Bug created'); +my $trademark_bug_id = $sel->get_value('//input[@name="id" and @type="hidden"]'); + +# itrequest + +_check_product('mozilla.org'); +_check_product('Infrastructure & Operations'); +_check_component('Infrastructure & Operations', 'WebOps: Other'); +_check_version('Infrastructure & Operations', 'other'); +_check_group('infra'); + +#$sel->open_ok("/$config->{bugzilla_installation}/enter_bug.cgi?product=mozilla.org&format=itrequest"); +#$sel->wait_for_page_to_load_ok(WAIT_TIME); +#$sel->title_is("Mozilla Corporation/Foundation IT Requests", "Open custom bug entry form - itrequest"); +#$sel->click_ok("component_webops_other", "Select request type"); +#$sel->type_ok("cc", $config->{'unprivileged_user_login'}, "Enter cc address"); +#$sel->type_ok("short_desc", "Bug created by Selenium", "Enter request summary"); +#$sel->type_ok("comment", "--- Bug created by Selenium ---", "Enter request description"); +#$sel->click_ok("commit", undef, "Submit bug data to post_bug.cgi"); +#$sel->wait_for_page_to_load_ok(WAIT_TIME); +#$sel->is_text_present_ok('has been added to the database', 'Bug created'); +#my $itrequest_bug_id = $sel->get_value('//input[@name="id" and @type="hidden"]'); + +# brownbag + +#$sel->open_ok("/$config->{bugzilla_installation}/enter_bug.cgi?product=mozilla.org&format=brownbag"); +#$sel->wait_for_page_to_load_ok(WAIT_TIME); +#$sel->title_is("Mozilla Corporation Brownbag Requests", "Open custom bug entry form - brownbag"); +#$sel->type_ok("presenter", "Bugzilla Administrator", "Enter presenter"); +#$sel->type_ok("topic", "Automated testing of Bugzilla", "Enter topic"); +#$sel->type_ok("date", "01/01/2012", "Enter date"); +#$sel->select_ok("time_hour", "value=1", "Select hour"); +#$sel->select_ok("time_minute", "value=30", "Select minute"); +#$sel->select_ok("ampm", "value=PM", "Select am/pm"); +#$sel->select_ok("audience", "value=Employees Only", "Select audience"); +#$sel->check_ok("airmozilla", "Select need airmozilla"); +#$sel->check_ok("dialin", "Select need dial in"); +#$sel->check_ok("archive", "Select need to be archived"); +#$sel->check_ok("ithelp", "Select need it help"); +#$sel->type_ok("cc", $config->{'unprivileged_user_login'}, "Enter cc address"); +#$sel->type_ok("description", "--- Bug created by Selenium ---", "Enter request description"); +#$sel->click_ok("commit", undef, "Submit bug data to post_bug.cgi"); +#$sel->wait_for_page_to_load_ok(WAIT_TIME); +#$sel->is_text_present_ok('has been added to the database', 'Bug created'); +#my $brownbag_bug_id = $sel->get_value('//input[@name="id" and @type="hidden"]'); + +# presentation + +#$sel->open_ok("/$config->{bugzilla_installation}/enter_bug.cgi?product=mozilla.org&format=presentation"); +#$sel->wait_for_page_to_load_ok(WAIT_TIME); +#$sel->title_is("Mozilla Corporation Mountain View Presentation Request", "Open custom bug entry form - presentation"); +#$sel->type_ok("presenter", "Bugzilla Administrator", "Enter presenter"); +#$sel->type_ok("topic", "Automated testing of Bugzilla", "Enter topic"); +#$sel->type_ok("date", "01/01/2012", "Enter date"); +#$sel->select_ok("time_hour", "value=1", "Select hour"); +#$sel->select_ok("time_minute", "value=30", "Select minute"); +#$sel->select_ok("ampm", "value=PM", "Select am/pm"); +#$sel->select_ok("audience", "value=Employees Only", "Select audience"); +#$sel->check_ok("airmozilla", "Select need airmozilla"); +#$sel->check_ok("dialin", "Select need dial in"); +#$sel->check_ok("archive", "Select need to be archived"); +#$sel->check_ok("ithelp", "Select need it help"); +#$sel->type_ok("cc", $config->{'unprivileged_user_login'}, "Enter cc address"); +#$sel->type_ok("description", "--- Bug created by Selenium ---", "Enter request description"); +#$sel->click_ok("commit", undef, "Submit bug data to post_bug.cgi"); +#$sel->wait_for_page_to_load_ok(WAIT_TIME); +#$sel->is_text_present_ok('has been added to the database', 'Bug created'); +#my $presentation_bug_id = $sel->get_value('//input[@name="id" and @type="hidden"]'); + +_check_component('mozilla.org', 'Discussion Forums'); + +#mozlist + +_check_version('mozilla.org', 'other'); +_check_component('mozilla.org', 'Discussion Forums'); + +$sel->open_ok("/$config->{bugzilla_installation}/enter_bug.cgi?product=mozilla.org&format=mozlist"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Mozilla Discussion Forum", "Open custom bug entry form - mozlist"); +$sel->type_ok("listName", "test-list", "Enter name for mailing list"); +$sel->type_ok("listAdmin", $config->{'admin_user_login'}, "Enter list administator"); +$sel->type_ok("cc", $config->{'unprivileged_user_login'}, "Enter cc address"); +$sel->check_ok("name=groups", "value=infra", "Select private group"); +$sel->type_ok("comment", "--- Bug created by Selenium ---", "Enter bug description"); +$sel->click_ok("commit", undef, "Submit bug data to post_bug.cgi"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->is_text_present_ok('has been added to the database', 'Bug created'); +my $mozlist_bug_id = $sel->get_value('//input[@name="id" and @type="hidden"]'); + +_check_product('Mozilla PR'); +_check_component('Mozilla PR', 'China - AMO'); +_check_group('mozilla-confidential'); + +#mozpr + +_check_group('pr-private'); + +#$sel->open_ok("/$config->{bugzilla_installation}/enter_bug.cgi?product=Mozilla PR&format=mozpr"); +#$sel->wait_for_page_to_load_ok(WAIT_TIME); +#$sel->title_is("Create a PR Request", "Open custom bug entry form - mozpr"); +#$sel->select_ok("location", "value=China", "Select location"); +#$sel->select_ok("component", "value=China - AMO", "Select component"); +#$sel->select_ok("fakecomp", "value=AMO", "Select fake component"); +#$sel->type_ok("cc", $config->{'unprivileged_user_login'}, "Enter cc address"); +#$sel->type_ok("short_desc", "Bug created by Selenium", "Enter bug summary"); +#$sel->type_ok("comment", "--- Bug created by Selenium ---", "Enter bug description"); +#$sel->click_ok("commit", undef, "Submit bug data to post_bug.cgi"); +#$sel->wait_for_page_to_load_ok(WAIT_TIME); +#$sel->is_text_present_ok('has been added to the database', 'Bug created'); +#my $mozpr_bug_id = $sel->get_value('//input[@name="id" and @type="hidden"]'); + +# legal + +_check_product('Legal'); +_check_component('Legal', 'Canonical'); +_check_component('Legal', 'Copyright'); +_check_group('mozilla-employee-confidential'); + +$sel->open_ok("/$config->{bugzilla_installation}/enter_bug.cgi?product=Legal&format=legal"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Mozilla Corporation Legal Requests", "Open custom bug entry form - legal"); +$sel->select_ok("component", "value=Canonical", "Select request type"); +$sel->type_ok("short_desc", "Bug created by Selenium", "Enter request summary"); +$sel->type_ok("cc", $config->{'unprivileged_user_login'}, "Enter cc address"); +$sel->type_ok("otherparty", "Other party", "Enter other party"); +$sel->type_ok("busobj", "Business objective", "Enter business objective"); +$sel->type_ok("comment", "--- Bug created by Selenium ---", "Enter request description"); +$sel->click_ok("commit", undef, "Submit bug data to post_bug.cgi"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->is_text_present_ok('has been added to the database', 'Bug created'); +my $legal_bug_id = $sel->get_value('//input[@name="id" and @type="hidden"]'); + +# poweredby + +_check_product('Websites', 'other'); +_check_component('Websites', 'www.mozilla.org'); +_check_user('liz@mozilla.com'); + +$sel->open_ok("/$config->{bugzilla_installation}/enter_bug.cgi?product=Websites&format=poweredby"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Powered by Mozilla Logo Requests", "Open custom bug entry form - poweredby"); +$sel->type_ok("short_desc", "Bug created by Selenium", "Enter bug summary"); +$sel->type_ok("comment", "--- Bug created by Selenium ---", "Enter bug description"); +$sel->click_ok("commit", undef, "Submit bug data to post_bug.cgi"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->is_text_present_ok('has been added to the database', 'Bug created'); +my $poweredby_bug_id = $sel->get_value('//input[@name="id" and @type="hidden"]'); + +set_parameters($sel, { "Bug Fields" => {"useclassification-on" => undef} }); +logout($sel); + +sub _check_product { + my ($product, $version) = @_; + + go_to_admin($sel); + $sel->click_ok("link=Products"); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->title_is("Select product"); + + my $product_description = "$product Description"; + + my $text = trim($sel->get_text("bugzilla-body")); + if ($text =~ /$product_description/) { + # Product exists already + return 1; + } + + $sel->click_ok("link=Add"); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->title_is("Add Product"); + $sel->type_ok("product", $product); + $sel->type_ok("description", $product_description); + $sel->type_ok("version", $version) if $version; + $sel->select_ok("default_op_sys_id", "Unspecified"); + $sel->select_ok("default_platform_id", "Unspecified"); + $sel->click_ok('//input[@type="submit" and @value="Add"]'); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $text = trim($sel->get_text("message")); + ok($text =~ /You will need to add at least one component before anyone can enter bugs against this product/, + "Display a reminder about missing components"); + + return 1; +} + +sub _check_component { + my ($product, $component) = @_; + + go_to_admin($sel); + $sel->click_ok("link=components"); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->title_is("Edit components for which product?"); + + $sel->click_ok("link=$product"); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->title_is("Select component of product '$product'"); + + my $component_description = "$component Description"; + + my $text = trim($sel->get_text("bugzilla-body")); + if ($text =~ /$component_description/) { + # Component exists already + return 1; + } + + # Add the watch user for component watching + my $watch_user = lc $component . "@" . lc $product . ".bugs"; + $watch_user =~ s/ & /-/; + $watch_user =~ s/\s+/\-/g; + $watch_user =~ s/://g; + + go_to_admin($sel); + $sel->click_ok("link=components"); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->title_is("Edit components for which product?"); + $sel->click_ok("link=$product"); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->title_is("Select component of product '$product'"); + $sel->click_ok("link=Add"); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->title_is("Add component to the $product product"); + $sel->type_ok("component", $component); + $sel->type_ok("description", $component_description); + $sel->type_ok("initialowner", $config->{'admin_user_login'}); + $sel->uncheck_ok("watch_user_auto"); + $sel->type_ok("watch_user", $watch_user); + $sel->check_ok("watch_user_auto"); + $sel->click_ok('//input[@type="submit" and @value="Add"]'); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->title_is("Component Created"); + $text = trim($sel->get_text("message")); + ok($text eq "The component $component has been created.", "Component successfully created"); + + return 1; +} + +sub _check_group { + my ($group) = @_; + + go_to_admin($sel); + $sel->click_ok("link=Groups"); + $sel->wait_for_page_to_load(WAIT_TIME); + $sel->title_is("Edit Groups"); + + my $group_description = "$group Description"; + + my $text = trim($sel->get_text("bugzilla-body")); + if ($text =~ /$group_description/) { + # Group exists already + return 1; + } + + $sel->title_is("Edit Groups"); + $sel->click_ok("link=Add Group"); + $sel->wait_for_page_to_load(WAIT_TIME); + $sel->title_is("Add group"); + $sel->type_ok("name", $group); + $sel->type_ok("desc", $group_description); + $sel->check_ok("isactive"); + $sel->check_ok("insertnew"); + $sel->click_ok("create"); + $sel->wait_for_page_to_load(WAIT_TIME); + $sel->title_is("New Group Created"); + my $group_id = $sel->get_value("group_id"); + + return 1; +} + +sub _check_version { + my ($product, $version) = @_; + + go_to_admin($sel); + $sel->click_ok("link=versions"); + $sel->wait_for_page_to_load(WAIT_TIME); + $sel->title_is("Edit versions for which product?"); + $sel->click_ok("link=$product"); + $sel->wait_for_page_to_load(WAIT_TIME); + + my $text = trim($sel->get_text("bugzilla-body")); + if ($text =~ /$version/) { + # Version exists already + return 1; + } + + $sel->click_ok("link=Add"); + $sel->wait_for_page_to_load(WAIT_TIME); + $sel->title_like(qr/^Add Version to Product/); + $sel->type_ok("version", $version); + $sel->click_ok("create"); + $sel->wait_for_page_to_load(WAIT_TIME); + $sel->title_is("Version Created"); + + return 1; +} + +sub _check_user { + my ($user) = @_; + + go_to_admin($sel); + $sel->click_ok("link=Users"); + $sel->wait_for_page_to_load(WAIT_TIME); + $sel->title_is("Search users"); + $sel->type_ok("matchstr", $user); + $sel->click_ok("search"); + $sel->wait_for_page_to_load(WAIT_TIME); + + my $text = trim($sel->get_text("bugzilla-body")); + if ($text =~ /$user/) { + # User exists already + return 1; + } + + $sel->click_ok("link=add a new user"); + $sel->wait_for_page_to_load(WAIT_TIME); + $sel->title_is('Add user'); + $sel->type_ok('login', $user); + $sel->type_ok('password', 'password'); + $sel->click_ok("add"); + $sel->wait_for_page_to_load(WAIT_TIME); + $sel->is_text_present('regexp:The user account .* has been created successfully'); + + return 1; +} diff --git a/qa/t/test_bmo_retire_values.t b/qa/t/test_bmo_retire_values.t new file mode 100644 index 000000000..f6086e0f9 --- /dev/null +++ b/qa/t/test_bmo_retire_values.t @@ -0,0 +1,388 @@ +# 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 strict; +use warnings; +use lib qw(lib); + +use Test::More "no_plan"; + +use QA::Util; + +my ($sel, $config) = get_selenium(); +my ($text, $bug_id); + +my $admin_user_login = $config->{admin_user_login}; + +log_in($sel, $config, 'admin'); +set_parameters($sel, { "Bug Fields" => {"useclassification-off" => undef, + "usetargetmilestone-on" => undef}, + "Administrative Policies" => {"allowbugdeletion-on" => undef}, + }); + +# create a clean bug + +file_bug_in_product($sel, "TestProduct"); +$sel->select_ok("component", "label=TestComponent"); +$sel->type_ok("short_desc", "testing testComponent"); +$sel->type_ok("comment", "testing"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +my $clean_bug_id = $sel->get_value("//input[\@name='id' and \@type='hidden']"); +$sel->is_text_present_ok('has been added to the database', "Bug $clean_bug_id created"); + +# +# component +# +# add a new component to TestProduct + +go_to_admin($sel); +$sel->click_ok("link=Products"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Select product"); +$sel->click_ok("link=TestProduct"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Edit Product 'TestProduct'"); +$sel->click_ok("link=Edit components:"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Select component of product 'TestProduct'"); +$text = trim($sel->get_text("bugzilla-body")); +if ($text =~ /TempComponent/) { + $sel->click_ok("//a[contains(\@href, 'editcomponents.cgi?action=del&product=TestProduct&component=TempComponent')]"); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->title_is("Delete component 'TempComponent' from 'TestProduct' product"); + $sel->click_ok("delete"); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->title_is("Component Deleted"); +} +$sel->click_ok("link=Add"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Add component to the TestProduct product"); +$sel->type_ok("component", "TempComponent"); +$sel->type_ok("description", "Temp component"); +$sel->type_ok("initialowner", $admin_user_login); +$sel->uncheck_ok("watch_user_auto"); +$sel->type_ok("watch_user", 'tempcomponent@testproduct.bugs'); +$sel->check_ok("watch_user_auto"); +$sel->click_ok('//input[@type="submit" and @value="Add"]'); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Component Created"); + +# create bug into TempComponent + +file_bug_in_product($sel, "TestProduct"); +$sel->select_ok("component", "label=TempComponent"); +$sel->type_ok("short_desc", "testing tempComponent"); +$sel->type_ok("comment", "testing"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$bug_id = $sel->get_value("//input[\@name='id' and \@type='hidden']"); +$sel->is_text_present_ok('has been added to the database', "Bug $bug_id created"); + +# disable TestProduct:TestComponent for bug entry + +go_to_admin($sel); +$sel->click_ok("link=Products"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Select product"); +$sel->click_ok("link=TestProduct"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Edit Product 'TestProduct'"); +$sel->click_ok("link=Edit components:"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Select component of product 'TestProduct'"); +$sel->click_ok("link=TempComponent"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Edit component 'TempComponent' of product 'TestProduct'"); +$sel->click_ok("isactive"); +$sel->click_ok("update"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Component Updated"); +$text = trim($sel->get_text("bugzilla-body")); +ok($text =~ /Disabled for bugs/, "Component deactivation confirmed"); + +# update bug TempComponent bug + +go_to_bug($sel, $bug_id); +# make sure the component is still tempcomponent +$sel->selected_label_is("component", 'TempComponent'); +# update +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->is_text_present_ok("Changes submitted for bug $bug_id"); +$sel->click_ok("link=bug $bug_id"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +# make sure the component is still tempcomponent +ok($sel->get_selected_labels("component"), 'TempComponent'); + +# try creating new bug with TempComponent + +file_bug_in_product($sel, "TestProduct"); +ok(!$sel->is_element_present( + q#//select[@id='component']/option[@value='TempComponent']#), + 'TempComponent is missing from create'); + +# try changing compoent of existing bug to TempComponent + +go_to_bug($sel, $clean_bug_id); +ok(!$sel->is_element_present( + q#//select[@id='component']/option[@value='TempComponent']#), + 'TempComponent is missing from update'); + +# delete TempComponent + +go_to_admin($sel); +$sel->click_ok("link=Products"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Select product"); +$sel->click_ok("link=TestProduct"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Edit Product 'TestProduct'"); +$sel->click_ok("link=Edit components:"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->click_ok("//a[contains(\@href, 'editcomponents.cgi?action=del&product=TestProduct&component=TempComponent')]"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Delete component 'TempComponent' from 'TestProduct' product"); +$sel->click_ok("delete"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Component Deleted"); + +# +# version +# + +# add a new version to TestProduct + +go_to_admin($sel); +$sel->click_ok("link=Products"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Select product"); +$sel->click_ok("link=TestProduct"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Edit Product 'TestProduct'"); +$sel->click_ok("link=Edit versions:"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Select version of product 'TestProduct'"); +$text = trim($sel->get_text("bugzilla-body")); +if ($text =~ /TempVersion/) { + $sel->click_ok("//a[contains(\@href, 'editversions.cgi?action=del&product=TestProduct&version=TempVersion')]"); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->title_is("Delete Version of Product 'TestProduct'"); + $sel->click_ok("delete"); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->title_is("Version Deleted"); +} +$sel->click_ok("link=Add"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Add Version to Product 'TestProduct'"); +$sel->type_ok("version", "TempVersion"); +$sel->click_ok("create"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Version Created"); + +# create bug with new version + +file_bug_in_product($sel, "TestProduct"); +$sel->select_ok("version", "label=TempVersion"); +$sel->type_ok("short_desc", "testing tempVersion"); +$sel->type_ok("comment", "testing"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$bug_id = $sel->get_value("//input[\@name='id' and \@type='hidden']"); +$sel->is_text_present_ok('has been added to the database', "Bug $bug_id created"); + +# disable new version for bug entry + +go_to_admin($sel); +$sel->click_ok("link=Products"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Select product"); +$sel->click_ok("link=TestProduct"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Edit Product 'TestProduct'"); +$sel->click_ok("link=Edit versions:"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Select version of product 'TestProduct'"); +$sel->click_ok("link=TempVersion"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Edit Version 'TempVersion' of product 'TestProduct'"); +$sel->click_ok("isactive"); +$sel->click_ok("update"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Version Updated"); +$text = trim($sel->get_text("bugzilla-body")); +ok($text =~ /Disabled for bugs/, "Version deactivation confirmed"); + +# update new version bug + +go_to_bug($sel, $bug_id); +# make sure the version is still tempversion +$sel->selected_label_is("version", 'TempVersion'); +# update +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->is_text_present_ok("Changes submitted for bug $bug_id"); +$sel->click_ok("link=bug $bug_id"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +# make sure the version is still tempversion +$sel->selected_label_is("version", 'TempVersion'); +# change the version so it can be deleted +$sel->select_ok("version", "label=unspecified"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->is_text_present_ok("Changes submitted for bug $bug_id"); + +# try creating new bug with new version + +file_bug_in_product($sel, "TestProduct"); +ok(!$sel->is_element_present( + q#//select[@id='version']/option[@value='TempVersion']#), + 'TempVersion is missing from create'); + +# try changing existing bug to new version + +go_to_bug($sel, $clean_bug_id); +ok(!$sel->is_element_present( + q#//select[@id='version']/option[@value='TempVersion']#), + 'TempVersion is missing from update'); + +# delete new version + +go_to_admin($sel); +$sel->click_ok("link=Products"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Select product"); +$sel->click_ok("link=TestProduct"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Edit Product 'TestProduct'"); +$sel->click_ok("link=Edit versions:"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Select version of product 'TestProduct'"); +$text = trim($sel->get_text("bugzilla-body")); +$sel->click_ok("//a[contains(\@href, 'editversions.cgi?action=del&product=TestProduct&version=TempVersion')]"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Delete Version of Product 'TestProduct'"); +$sel->click_ok("delete"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Version Deleted"); + +# +# milestone +# + +# add a milestone to TestProduct + +go_to_admin($sel); +$sel->click_ok("link=Products"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Select product"); +$sel->click_ok("link=TestProduct"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Edit Product 'TestProduct'"); +$sel->click_ok("link=Edit milestones:"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Select milestone of product 'TestProduct'"); +$text = trim($sel->get_text("bugzilla-body")); +if ($text =~ /TempMilestone/) { + $sel->click_ok("//a[contains(\@href, 'editmilestones.cgi?action=del&product=TestProduct&milestone=TempMilestone')]"); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->title_is("Delete Milestone of Product 'TestProduct'"); + $sel->click_ok("delete"); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->title_is("Milestone Deleted"); +} +$sel->click_ok("link=Add"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Add Milestone to Product 'TestProduct'"); +$sel->type_ok("milestone", "TempMilestone"); +$sel->type_ok("sortkey", "999"); +$sel->click_ok("create"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Milestone Created"); + +# create bug with milestone + +file_bug_in_product($sel, "TestProduct"); +$sel->select_ok("target_milestone", "label=TempMilestone"); +$sel->type_ok("short_desc", "testing tempMilestone"); +$sel->type_ok("comment", "testing"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$bug_id = $sel->get_value("//input[\@name='id' and \@type='hidden']"); +$sel->is_text_present_ok('has been added to the database', "Bug $bug_id created"); + +# disable milestone for bug entry + +go_to_admin($sel); +$sel->click_ok("link=Products"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Select product"); +$sel->click_ok("link=TestProduct"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Edit Product 'TestProduct'"); +$sel->click_ok("link=Edit milestones:"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Select milestone of product 'TestProduct'"); +$sel->click_ok("link=TempMilestone"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Edit Milestone 'TempMilestone' of product 'TestProduct'"); +$sel->click_ok("isactive"); +$sel->click_ok("update"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Milestone Updated"); +$text = trim($sel->get_text("bugzilla-body")); +ok($text =~ /Disabled for bugs/, "Milestone deactivation confirmed"); + +# update milestone bug + +go_to_bug($sel, $bug_id); +# make sure the milestone is still tempmilestone +$sel->selected_label_is("target_milestone", 'TempMilestone'); +# update +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->is_text_present_ok("Changes submitted for bug $bug_id"); +$sel->click_ok("link=bug $bug_id"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +# make sure the milestone is still tempmilestone +$sel->selected_label_is("target_milestone", 'TempMilestone'); + +# try creating new bug with milestone + +file_bug_in_product($sel, "TestProduct"); +ok(!$sel->is_element_present( + q#//select[@id='target_milestone']/option[@value='TempMilestone']#), + 'TempMilestone is missing from create'); + +# try changing existing bug to milestone + +go_to_bug($sel, $clean_bug_id); +ok(!$sel->is_element_present( + q#//select[@id='target_milestone']/option[@value='TempMilestone']#), + 'TempMilestone is missing from update'); + +# delete milestone + +go_to_admin($sel); +$sel->click_ok("link=Products"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Select product"); +$sel->click_ok("link=TestProduct"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Edit Product 'TestProduct'"); +$sel->click_ok("link=Edit milestones:"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Select milestone of product 'TestProduct'"); +$text = trim($sel->get_text("bugzilla-body")); +$sel->click_ok("//a[contains(\@href, 'editmilestones.cgi?action=del&product=TestProduct&milestone=TempMilestone')]"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Delete Milestone of Product 'TestProduct'"); +$sel->click_ok("delete"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Milestone Deleted"); + +logout($sel); diff --git a/qa/t/test_bug_edit.t b/qa/t/test_bug_edit.t new file mode 100644 index 000000000..64deafcf6 --- /dev/null +++ b/qa/t/test_bug_edit.t @@ -0,0 +1,504 @@ +# 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 strict; +use warnings; +use lib qw(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} }); + +# Clear the saved search, in case this test didn't complete previously. +if ($sel->is_text_present("My bugs from QA_Selenium")) { + $sel->click_ok("link=My bugs from QA_Selenium"); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->title_is("Bug List: My bugs from QA_Selenium"); + $sel->click_ok("link=Forget Search 'My bugs from QA_Selenium'"); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->title_is("Search is gone"); + $sel->is_text_present_ok("OK, the My bugs from QA_Selenium search is gone"); +} + +# Just in case the test failed before completion previously, reset the CANEDIT bit. +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; + +clear_canedit_on_testproduct($sel, $master_gid); +logout($sel); + +# First create a bug. + +log_in($sel, $config, 'QA_Selenium_TEST'); +file_bug_in_product($sel, 'TestProduct'); +$sel->select_ok("bug_severity", "label=critical"); +$sel->type_ok("short_desc", "Test bug editing"); +$sel->type_ok("comment", "ploc"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +my $bug1_id = $sel->get_value('//input[@name="id" and @type="hidden"]'); +$sel->is_text_present_ok('has been added to the database', "Bug $bug1_id created"); + +# Now edit field values of the bug you just filed. + +$sel->select_ok("rep_platform", "label=Other"); +$sel->select_ok("op_sys", "label=Other"); +$sel->select_ok("priority", "label=Highest"); +$sel->select_ok("bug_severity", "label=blocker"); +$sel->type_ok("bug_file_loc", "foo.cgi?action=bar"); +$sel->type_ok("status_whiteboard", "[Selenium was here]"); +$sel->type_ok("comment", "new comment from me :)"); +$sel->select_ok("bug_status", "label=RESOLVED"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->is_text_present_ok("Changes submitted for bug $bug1_id"); + +# Now move the bug into another product, which has a mandatory group. + +$sel->click_ok("link=bug $bug1_id"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_like(qr/^$bug1_id /); +$sel->select_ok("product", "label=QA-Selenium-TEST"); +$sel->type_ok("comment", "moving to QA-Selenium-TEST"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Verify New Product Details..."); +$sel->select_ok("component", "label=QA-Selenium-TEST"); +$sel->is_element_present_ok('//input[@type="checkbox" and @name="groups" and @value="QA-Selenium-TEST"]'); +ok(!$sel->is_editable('//input[@type="checkbox" and @name="groups" and @value="QA-Selenium-TEST"]'), "QA-Selenium-TEST group not editable"); +$sel->is_checked_ok('//input[@type="checkbox" and @name="groups" and @value="QA-Selenium-TEST"]', "QA-Selenium-TEST group is selected"); +$sel->click_ok("change_product"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->is_text_present_ok("Changes submitted for bug $bug1_id"); +$sel->click_ok("link=bug $bug1_id"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_like(qr/^$bug1_id /); +$sel->select_ok("bug_severity", "label=normal"); +$sel->select_ok("priority", "label=High"); +$sel->select_ok("rep_platform", "label=All"); +$sel->select_ok("op_sys", "label=All"); +$sel->click_ok("cc_edit_area_showhide"); +$sel->type_ok("newcc", $config->{admin_user_login}); +$sel->type_ok("comment", "Unchecking the reporter_accessible checkbox"); +# This checkbox is checked by default. +$sel->click_ok("reporter_accessible"); +$sel->select_ok("bug_status", "label=VERIFIED"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->is_text_present_ok("Changes submitted for bug $bug1_id"); +$sel->click_ok("link=bug $bug1_id"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_like(qr/^$bug1_id /); +$sel->type_ok("comment", "I am the reporter, but I can see the bug anyway as I belong to the mandatory group"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->is_text_present_ok("Changes submitted for bug $bug1_id"); +logout($sel); + +# The admin is not in the mandatory group, but he has been CC'ed, +# so he can view and edit the bug (as he has editbugs privs by inheritance). + +log_in($sel, $config, 'admin'); +go_to_bug($sel, $bug1_id); +$sel->select_ok("bug_severity", "label=blocker"); +$sel->select_ok("priority", "label=Highest"); +$sel->type_ok("status_whiteboard", "[Selenium was here][admin too]"); +$sel->select_ok("bug_status", "label=CONFIRMED"); +$sel->click_ok("bz_assignee_edit_action"); +$sel->type_ok("assigned_to", $config->{admin_user_login}); +$sel->type_ok("comment", "I have editbugs privs. Taking!"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->is_text_present_ok("Changes submitted for bug $bug1_id"); + +$sel->click_ok("link=bug $bug1_id"); +$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", $config->{unprivileged_user_login}); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->is_text_present_ok("Changes submitted for bug $bug1_id"); +logout($sel); + +# The powerless user can see the restricted bug, as he has been CC'ed. + +log_in($sel, $config, 'unprivileged'); +go_to_bug($sel, $bug1_id); +$sel->is_text_present_ok("I have editbugs privs. Taking!"); +logout($sel); + +# Now turn off cclist_accessible, which will prevent +# the powerless user to see the bug again. + +log_in($sel, $config, 'admin'); +go_to_bug($sel, $bug1_id); +$sel->click_ok("cclist_accessible"); +$sel->type_ok("comment", "I am allowed to turn off cclist_accessible despite not being in the mandatory group"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->is_text_present_ok("Changes submitted for bug $bug1_id"); +logout($sel); + +# The powerless user cannot see the restricted bug anymore. + +log_in($sel, $config, 'unprivileged'); +$sel->type_ok("quicksearch_top", $bug1_id); +$sel->click_ok("find_top"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Access Denied"); +$sel->is_text_present_ok("You are not authorized to access bug #$bug1_id"); +logout($sel); + +# Move the bug back to TestProduct, which has no group restrictions. + +log_in($sel, $config, 'admin'); +go_to_bug($sel, $bug1_id); +$sel->select_ok("product", "label=TestProduct"); +# When selecting a new product, Bugzilla tries to reassign the bug by default, +# so we have to uncheck it. +$sel->click_ok("set_default_assignee"); +$sel->uncheck_ok("set_default_assignee"); +$sel->type_ok("comment", "-> Moving back to Testproduct."); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Verify New Product Details..."); +$sel->select_ok("component", "label=TestComponent"); +$sel->is_text_present_ok("These groups are not legal for the 'TestProduct' product or you are not allowed to restrict bugs to these groups"); +$sel->is_element_present_ok('//input[@type="checkbox" and @name="groups" and @value="QA-Selenium-TEST"]'); +ok(!$sel->is_editable('//input[@type="checkbox" and @name="groups" and @value="QA-Selenium-TEST"]'), "QA-Selenium-TEST group not editable"); +ok(!$sel->is_checked('//input[@type="checkbox" and @name="groups" and @value="QA-Selenium-TEST"]'), "QA-Selenium-TEST group not selected"); +$sel->is_element_present_ok('//input[@type="checkbox" and @name="groups" and @value="Master"]'); +$sel->is_editable_ok('//input[@type="checkbox" and @name="groups" and @value="Master"]', "Master group is editable"); +ok(!$sel->is_checked('//input[@type="checkbox" and @name="groups" and @value="Master"]'), "Master group not selected by default"); +$sel->click_ok("change_product"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->is_text_present_ok("Changes submitted for bug $bug1_id"); +$sel->click_ok("link=bug $bug1_id"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_like(qr/^$bug1_id /); +$sel->click_ok("cclist_accessible"); +$sel->type_ok("comment", "I am allowed to turn off cclist_accessible despite not being in the mandatory group"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->is_text_present_ok("Changes submitted for bug $bug1_id"); +logout($sel); + +# The unprivileged user can view the bug again, but cannot +# edit it, except adding comments. + +log_in($sel, $config, 'unprivileged'); +go_to_bug($sel, $bug1_id); +$sel->type_ok("comment", "I have no privs, I can only comment (and remove people from the CC list)"); +ok(!$sel->is_element_present('//select[@name="product"]'), "Product field not editable"); +ok(!$sel->is_element_present('//select[@name="bug_severity"]'), "Severity field not editable"); +ok(!$sel->is_element_present('//select[@name="priority"]'), "Priority field not editable"); +ok(!$sel->is_element_present('//select[@name="op_sys"]'), "OS field not editable"); +ok(!$sel->is_element_present('//select[@name="rep_platform"]'), "Hardware field not editable"); +$sel->click_ok("cc_edit_area_showhide"); +$sel->add_selection_ok("cc", "label=" . $config->{admin_user_login}); +$sel->click_ok("removecc"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->is_text_present_ok("Changes submitted for bug $bug1_id"); +logout($sel); + +# Now let's test the CANEDIT bit. + +log_in($sel, $config, 'admin'); +edit_product($sel, "TestProduct"); +$sel->click_ok("link=Edit Group Access Controls:"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Edit Group Controls for TestProduct"); +$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 TestProduct"); + +# The user is in the master group, so he can comment. + +go_to_bug($sel, $bug1_id); +$sel->type_ok("comment", "Do nothing except adding a comment..."); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->is_text_present_ok("Changes submitted for bug $bug1_id"); +logout($sel); + +# This user is not in the master group, so he cannot comment. + +log_in($sel, $config, 'QA_Selenium_TEST'); +go_to_bug($sel, $bug1_id); +$sel->type_ok("comment", "Just a comment too..."); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Product Edit Access Denied"); +$sel->is_text_present_ok("You are not permitted to edit bugs in product TestProduct."); +logout($sel); + +# Test searches and "format for printing". + +log_in($sel, $config, 'admin'); +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->remove_all_selections_ok("resolution"); +$sel->is_checked_ok("emailassigned_to1"); +$sel->select_ok("emailtype1", "label=is"); +$sel->type_ok("email1", $config->{admin_user_login}); +$sel->check_ok("emailassigned_to2"); +$sel->check_ok("emailqa_contact2"); +$sel->check_ok("emailcc2"); +$sel->select_ok("emailtype2", "label=is"); +$sel->type_ok("email2", $config->{QA_Selenium_TEST_user_login}); +$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", "My bugs from QA_Selenium"); +$sel->click_ok("remember"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Search created"); +$sel->is_text_present_ok("OK, you have a new search named My bugs from QA_Selenium."); +$sel->click_ok("link=My bugs from QA_Selenium"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Bug List: My bugs from QA_Selenium"); +$sel->click_ok("long_format"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Full Text Bug Listing"); +$sel->is_text_present_ok("Bug $bug1_id"); +$sel->is_text_present_ok("Status: CONFIRMED"); +$sel->is_text_present_ok("Reporter: QA-Selenium-TEST <$config->{QA_Selenium_TEST_user_login}>"); +$sel->is_text_present_ok("Assignee: QA Admin <$config->{admin_user_login}>"); +$sel->is_text_present_ok("Severity: blocker"); +$sel->is_text_present_ok("Priority: Highest"); +$sel->is_text_present_ok("I have no privs, I can only comment"); +logout($sel); + +# Let's create a 2nd bug by this user so that we can test mass-change +# using the saved search the admin just created. + +log_in($sel, $config, 'QA_Selenium_TEST'); +file_bug_in_product($sel, 'TestProduct'); +$sel->select_ok("bug_severity", "label=blocker"); +$sel->type_ok("short_desc", "New bug from me"); +# We turned on the CANEDIT bit for TestProduct. +$sel->type_ok("comment", "I can enter a new bug, but not edit it, right?"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +my $bug2_id = $sel->get_value('//input[@name="id" and @type="hidden"]'); +$sel->is_text_present_ok('has been added to the database', "Bug $bug2_id created"); + +# Clicking the "Back" button and resubmitting the form again should trigger a suspicous action error. + +$sel->go_back_ok(); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Enter Bug: TestProduct"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Suspicious Action"); +$sel->is_text_present_ok("you have no valid token for the create_bug action"); +$sel->click_ok('//input[@value="Confirm Changes"]'); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->is_text_present_ok('has been added to the database', 'Bug created'); +$sel->type_ok("comment", "New comment not allowed"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Product Edit Access Denied"); +$sel->is_text_present_ok("You are not permitted to edit bugs in product TestProduct."); +logout($sel); + +# Reassign the newly created bug to the admin. + +log_in($sel, $config, 'admin'); +go_to_bug($sel, $bug2_id); +$sel->click_ok("bz_assignee_edit_action"); +$sel->type_ok("assigned_to", $config->{admin_user_login}); +$sel->type_ok("comment", "Taking!"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->is_text_present_ok("Changes submitted for bug $bug2_id"); + +# Test mass-change. + +$sel->click_ok("link=My bugs from QA_Selenium"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Bug List: My bugs from QA_Selenium"); +$sel->is_text_present_ok("2 bugs found"); +$sel->click_ok("link=Change Several Bugs at Once"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Bug List"); +$sel->click_ok("check_all"); +$sel->type_ok("comment", 'Mass change"'); +$sel->select_ok("bug_status", "label=RESOLVED"); +$sel->select_ok("resolution", "label=WORKSFORME"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Bugs processed"); + +$sel->click_ok("link=bug $bug1_id"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_like(qr/$bug1_id /); +$sel->selected_label_is("resolution", "WORKSFORME"); +$sel->select_ok("resolution", "label=INVALID"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->is_text_present_ok("Changes submitted for bug $bug1_id"); + +$sel->click_ok("link=bug $bug1_id"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_like(qr/$bug1_id /); +$sel->selected_label_is("resolution", "INVALID"); + +$sel->click_ok("link=History"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Changes made to bug $bug1_id"); +$sel->is_text_present_ok("URL foo.cgi?action=bar"); +$sel->is_text_present_ok("Severity critical blocker"); +$sel->is_text_present_ok("Whiteboard [Selenium was here] [Selenium was here][admin too]"); +$sel->is_text_present_ok("Product QA-Selenium-TEST TestProduct"); +$sel->is_text_present_ok("Status CONFIRMED RESOLVED"); + +# Last step: move bugs to another DB, if the extension is enabled. + +# if ($config->{test_extensions}) { +# set_parameters($sel, { "Bug Moving" => {"move-to-url" => {type => "text", value => 'http://www.foo.com/'}, +# "move-to-address" => {type => "text", value => 'import@foo.com'}, +# "movers" => {type => "text", value => $config->{admin_user_login}} +# } +# }); +# +# # Mass-move has been removed, see 581690. +# # Restore these tests once this bug is fixed. +# # $sel->click_ok("link=My bugs from QA_Selenium"); +# # $sel->wait_for_page_to_load_ok(WAIT_TIME); +# # $sel->title_is("Bug List: My bugs from QA_Selenium"); +# # $sel->is_text_present_ok("2 bugs found"); +# # $sel->click_ok("link=Change Several Bugs at Once"); +# # $sel->wait_for_page_to_load_ok(WAIT_TIME); +# # $sel->title_is("Bug List"); +# # $sel->click_ok("check_all"); +# # $sel->type_ok("comment", "-> moved"); +# # $sel->click_ok('oldbugmove'); +# # $sel->wait_for_page_to_load_ok(WAIT_TIME); +# # $sel->title_is("Bugs processed"); +# # $sel->is_text_present_ok("Bug $bug1_id has been moved to another database"); +# # $sel->is_text_present_ok("Bug $bug2_id has been moved to another database"); +# # $sel->click_ok("link=Bug $bug2_id"); +# # $sel->wait_for_page_to_load_ok(WAIT_TIME); +# # $sel->title_like(qr/^$bug2_id/); +# # $sel->selected_label_is("resolution", "MOVED"); +# +# go_to_bug($sel, $bug2_id); +# $sel->click_ok('oldbugmove'); +# $sel->wait_for_page_to_load_ok(WAIT_TIME); +# $sel->is_text_present_ok("Changes submitted for bug $bug2_id"); +# $sel->click_ok("link=bug $bug2_id"); +# $sel->wait_for_page_to_load_ok(WAIT_TIME); +# $sel->title_like(qr/$bug2_id /); +# $sel->selected_label_is("resolution", "MOVED"); +# $sel->is_text_present_ok("Bug moved to http://www.foo.com/."); +# +# # Disable bug moving again. +# set_parameters($sel, { "Bug Moving" => {"movers" => {type => "text", value => ""}} }); +# } + +# Make sure token checks are working correctly for single bug editing and mass change, +# first with no token, then with an invalid token. + +foreach my $params (["no_token_single_bug", ""], ["invalid_token_single_bug", "&token=1"]) { + my ($comment, $token) = @$params; + $sel->open_ok("/$config->{bugzilla_installation}/process_bug.cgi?id=$bug1_id&comment=$comment$token", + undef, "Edit a single bug with " . ($token ? "an invalid" : "no") . " token"); + $sel->title_is("Suspicious Action"); + $sel->is_text_present_ok($token ? "an invalid token" : "web browser directly"); + $sel->click_ok("confirm"); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->is_text_present_ok("Changes submitted for bug $bug1_id"); + $sel->click_ok("link=bug $bug1_id"); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->title_like(qr/^$bug1_id /); + $sel->is_text_present_ok($comment); +} + +foreach my $params (["no_token_mass_change", ""], ["invalid_token_mass_change", "&token=1"]) { + my ($comment, $token) = @$params; + $sel->open_ok("/$config->{bugzilla_installation}/process_bug.cgi?id_$bug1_id=1&id_$bug2_id=1&comment=$comment$token", + undef, "Mass change with " . ($token ? "an invalid" : "no") . " token"); + $sel->title_is("Suspicious Action"); + $sel->is_text_present_ok("no valid token for the buglist_mass_change action"); + $sel->click_ok("confirm"); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->title_is("Bugs processed"); + foreach my $bug_id ($bug1_id, $bug2_id) { + $sel->click_ok("link=bug $bug_id"); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->title_like(qr/^$bug_id /); + $sel->is_text_present_ok($comment); + next if $bug_id == $bug2_id; + $sel->go_back_ok(); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->title_is("Bugs processed"); + } +} + +# Now move these bugs out of our radar. + +$sel->click_ok("link=My bugs from QA_Selenium"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Bug List: My bugs from QA_Selenium"); +$sel->is_text_present_ok("2 bugs found"); +$sel->click_ok("link=Change Several Bugs at Once"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Bug List"); +$sel->click_ok("check_all"); +$sel->type_ok("comment", "Reassigning to the reporter"); +$sel->type_ok("assigned_to", $config->{QA_Selenium_TEST_user_login}); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Bugs processed"); + +# Now delete the saved search. + +$sel->click_ok("link=My bugs from QA_Selenium"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Bug List: My bugs from QA_Selenium"); +$sel->click_ok("link=Forget Search 'My bugs from QA_Selenium'"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Search is gone"); +$sel->is_text_present_ok("OK, the My bugs from QA_Selenium search is gone"); + +# Reset the CANEDIT bit. We want it to be turned off by default. +clear_canedit_on_testproduct($sel, $master_gid); +logout($sel); + +sub clear_canedit_on_testproduct { + my ($sel, $master_gid) = @_; + + edit_product($sel, "TestProduct"); + $sel->click_ok("link=Edit Group Access Controls:"); + $sel->wait_for_page_to_load_ok(WAIT_TIME); + $sel->title_is("Edit Group Controls for TestProduct"); + $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 TestProduct"); +} diff --git a/qa/t/test_choose_priority.t b/qa/t/test_choose_priority.t new file mode 100644 index 000000000..a35823327 --- /dev/null +++ b/qa/t/test_choose_priority.t @@ -0,0 +1,27 @@ +# 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 strict; +use warnings; +use lib qw(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); diff --git a/qa/t/test_classifications.t b/qa/t/test_classifications.t new file mode 100644 index 000000000..ec5597d9e --- /dev/null +++ b/qa/t/test_classifications.t @@ -0,0 +1,146 @@ +# 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 strict; +use warnings; +use lib qw(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&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&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"); +$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'); +$sel->type_ok("short_desc", "Bug in classification cone"); +$sel->type_ok("comment", "Created by Selenium with classifications turned on"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +my $bug1_id = $sel->get_value('//input[@name="id" and @type="hidden"]'); +$sel->is_text_present_ok('has been added to the database', "Bug $bug1_id created"); + +# 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"); + +# The classification the bug belongs to is no longer displayed since bug 452733. +# Keeping the code here in case it comes back in a future release. :) +# go_to_bug($sel, $bug1_id); +# $sel->is_text_present_ok('[ctwo]'); + +# 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); diff --git a/qa/t/test_config.t b/qa/t/test_config.t new file mode 100644 index 000000000..e2f82fc21 --- /dev/null +++ b/qa/t/test_config.t @@ -0,0 +1,45 @@ +# 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 strict; +use warnings; +use lib qw(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); diff --git a/qa/t/test_create_user_accounts.t b/qa/t/test_create_user_accounts.t new file mode 100644 index 000000000..18b555aaf --- /dev/null +++ b/qa/t/test_create_user_accounts.t @@ -0,0 +1,129 @@ +# 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 strict; +use warnings; +use lib qw(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->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('//input[@value="Create Account"]'); +$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('//input[@value="Create Account"]'); +$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 a while and try again/, "Too soon for this account"); + +# These accounts do not pass the regexp. +my @accounts = ('test@yahoo.com', 'test@bugzilla.net', 'test@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"); + $sel->type_ok("login", $account); + $sel->click_ok('//input[@value="Create Account"]'); + $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 and should cause a javascript alert. +@accounts = qw( + test\bugzilla@bugzilla.test + testbugzilla.test + test@bugzilla + test@bugzilla. + 'test'@bugzilla.test + test&test@bugzilla.test + [test]@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"); + $sel->type_ok("login", $account); + $sel->click_ok('//input[@value="Create Account"]'); + ok($sel->get_alert() =~ /The e-mail address doesn't pass our syntax checking for a legal email address/, + '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('//input[@value="Create Account"]'); +$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-@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); diff --git a/qa/t/test_custom_fields.t b/qa/t/test_custom_fields.t new file mode 100644 index 000000000..7c69e4bbf --- /dev/null +++ b/qa/t/test_custom_fields.t @@ -0,0 +1,459 @@ +# 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 strict; +use warnings; +use lib qw(lib); + +use Test::More "no_plan"; + +use QA::Util; + +my ($sel, $config) = get_selenium(); +log_in($sel, $config, 'admin'); + +# Create new bug to test custom fields + +file_bug_in_product($sel, 'TestProduct'); +my $bug_summary = "What's your ID?"; +$sel->type_ok("short_desc", $bug_summary); +$sel->type_ok("comment", "Use the ID of this bug to generate a unique custom field name."); +$sel->type_ok("bug_severity", "label=normal"); +my $bug1_id = create_bug($sel, $bug_summary); + +# Create custom fields + +go_to_admin($sel); +$sel->click_ok("link=Custom Fields"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Custom Fields"); +$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", "cf_qa_freetext_$bug1_id"); +$sel->type_ok("desc", "Freetext$bug1_id"); +$sel->select_ok("type", "label=Free Text"); +$sel->type_ok("sortkey", $bug1_id); +# These values are off by default. +$sel->value_is("enter_bug", "off"); +$sel->value_is("obsolete", "off"); +$sel->click_ok("create"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Custom Field Created"); +$sel->is_text_present_ok("The new custom field 'cf_qa_freetext_$bug1_id' has been successfully created."); + +$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", "cf_qa_list_$bug1_id"); +$sel->type_ok("desc", "List$bug1_id"); +$sel->select_ok("type", "label=Drop Down"); +$sel->type_ok("sortkey", $bug1_id); +$sel->click_ok("enter_bug"); +$sel->value_is("enter_bug", "on"); +$sel->click_ok("new_bugmail"); +$sel->value_is("new_bugmail", "on"); +$sel->value_is("obsolete", "off"); +$sel->click_ok("create"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Custom Field Created"); +$sel->is_text_present_ok("The new custom field 'cf_qa_list_$bug1_id' has been successfully created."); + +$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", "cf_qa_bugid_$bug1_id"); +$sel->type_ok("desc", "Reference$bug1_id"); +$sel->select_ok("type", "label=Bug ID"); +$sel->type_ok("sortkey", $bug1_id); +$sel->type_ok("reverse_desc", "IsRef$bug1_id"); +$sel->click_ok("enter_bug"); +$sel->value_is("enter_bug", "on"); +$sel->value_is("obsolete", "off"); +$sel->click_ok("create"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Custom Field Created"); +$sel->is_text_present_ok("The new custom field 'cf_qa_bugid_$bug1_id' has been successfully created."); + +# Add values to the custom fields. + +$sel->click_ok("link=cf_qa_list_$bug1_id"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Edit the Custom Field 'cf_qa_list_$bug1_id' (List$bug1_id)"); +$sel->click_ok("link=Edit legal values for this field"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Select value for the 'List$bug1_id' (cf_qa_list_$bug1_id) field"); + +$sel->click_ok("link=Add"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Add Value for the 'List$bug1_id' (cf_qa_list_$bug1_id) field"); +$sel->type_ok("value", "have fun?"); +$sel->type_ok("sortkey", "805"); +$sel->click_ok("create"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("New Field Value Created"); +$sel->is_text_present_ok("The value have fun? has been added as a valid choice for the List$bug1_id (cf_qa_list_$bug1_id) field."); + +$sel->click_ok("link=Add"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Add Value for the 'List$bug1_id' (cf_qa_list_$bug1_id) field"); +$sel->type_ok("value", "storage"); +$sel->type_ok("sortkey", "49"); +$sel->click_ok("create"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("New Field Value Created"); +$sel->is_text_present_ok("The value storage has been added as a valid choice for the List$bug1_id (cf_qa_list_$bug1_id) field."); + +# Also create a new bug status and a new resolution. + +go_to_admin($sel); +$sel->click_ok("link=Field Values"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Edit values for which field?"); +$sel->click_ok("link=Resolution"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Select value for the 'Resolution' (resolution) field"); +$sel->click_ok("link=Add"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Add Value for the 'Resolution' (resolution) field"); +$sel->type_ok("value", "UPSTREAM"); +$sel->type_ok("sortkey", 450); +$sel->click_ok("create"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("New Field Value Created"); + +go_to_admin($sel); +$sel->click_ok("link=Field Values"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Edit values for which field?"); +$sel->click_ok("link=Status"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Select value for the 'Status' (bug_status) field"); +$sel->click_ok("link=Add"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Add Value for the 'Status' (bug_status) field"); +$sel->type_ok("value", "SUSPENDED"); +$sel->type_ok("sortkey", 250); +$sel->click_ok("open_status"); +$sel->click_ok("create"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("New Field Value Created"); + +$sel->click_ok("link=Add"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Add Value for the 'Status' (bug_status) field"); +$sel->type_ok("value", "IN_QA"); +$sel->type_ok("sortkey", 550); +$sel->click_ok("closed_status"); +$sel->click_ok("create"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("New Field Value Created"); + +$sel->click_ok("link=status workflow page"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Edit Workflow"); +$sel->click_ok('//td[@title="From UNCONFIRMED to SUSPENDED"]//input[@type="checkbox"]'); +$sel->click_ok('//td[@title="From CONFIRMED to SUSPENDED"]//input[@type="checkbox"]'); +$sel->click_ok('//td[@title="From SUSPENDED to CONFIRMED"]//input[@type="checkbox"]'); +$sel->click_ok('//td[@title="From SUSPENDED to IN_PROGRESS"]//input[@type="checkbox"]'); +$sel->click_ok('//td[@title="From RESOLVED to IN_QA"]//input[@type="checkbox"]'); +$sel->click_ok('//td[@title="From IN_QA to VERIFIED"]//input[@type="checkbox"]'); +$sel->click_ok('//td[@title="From IN_QA to CONFIRMED"]//input[@type="checkbox"]'); +$sel->click_ok('//input[@value="Commit Changes"]'); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Edit Workflow"); + +# Create new bug to test custom fields in bug creation page + +file_bug_in_product($sel, 'TestProduct'); +$sel->is_text_present_ok("List$bug1_id:"); +$sel->is_element_present_ok("cf_qa_list_$bug1_id"); +$sel->is_text_present_ok("Reference$bug1_id:"); +$sel->is_element_present_ok("cf_qa_bugid_$bug1_id"); +ok(!$sel->is_text_present("Freetext$bug1_id:"), "Freetext$bug1_id is not displayed"); +ok(!$sel->is_element_present("cf_qa_freetext_$bug1_id"), "cf_qa_freetext_$bug1_id is not available"); +my $bug_summary2 = "Et de un"; +$sel->type_ok("short_desc", $bug_summary2); +$sel->select_ok("bug_severity", "critical"); +$sel->type_ok("cf_qa_bugid_$bug1_id", $bug1_id); +$sel->type_ok("comment", "hops!"); +my $bug2_id = create_bug($sel, $bug_summary2); + +# Both fields are editable. + +$sel->type_ok("cf_qa_freetext_$bug1_id", "bonsai"); +$sel->selected_label_is("cf_qa_list_$bug1_id", "---"); +$sel->select_ok("bug_status", "label=SUSPENDED"); +edit_bug($sel, $bug2_id); + +go_to_bug($sel, $bug1_id); +$sel->type_ok("cf_qa_freetext_$bug1_id", "dumbo"); +$sel->select_ok("cf_qa_list_$bug1_id", "label=storage"); +$sel->is_text_present_ok("IsRef$bug1_id: $bug2_id"); +$sel->select_ok("bug_status", "RESOLVED"); +$sel->select_ok("resolution", "UPSTREAM"); +edit_bug_and_return($sel, $bug1_id, $bug_summary); +$sel->select_ok("bug_status", "IN_QA"); +edit_bug_and_return($sel, $bug1_id, $bug_summary); + +$sel->click_ok("link=Format For Printing"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Full Text Bug Listing"); +$sel->is_text_present_ok("Freetext$bug1_id: dumbo"); +$sel->is_text_present_ok("List$bug1_id: storage"); +$sel->is_text_present_ok("Status: IN_QA UPSTREAM"); +go_to_bug($sel, $bug2_id); +$sel->select_ok("cf_qa_list_$bug1_id", "label=storage"); +edit_bug($sel, $bug2_id); + +# Test searching for bugs using the custom fields + +open_advanced_search_page($sel); +$sel->remove_all_selections_ok("product"); +$sel->add_selection_ok("product", "TestProduct"); +$sel->remove_all_selections("bug_status"); +$sel->remove_all_selections("resolution"); +$sel->select_ok("f1", "label=List$bug1_id"); +$sel->select_ok("o1", "label=is equal to"); +$sel->type_ok("v1", "storage"); +$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->is_text_present_ok("What's your ID?"); +$sel->is_text_present_ok("Et de un"); + +# Now edit custom fields in mass changes. + +$sel->click_ok("link=Change Several Bugs at Once"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Bug List"); +$sel->click_ok("check_all"); +$sel->select_ok("cf_qa_list_$bug1_id", "label=---"); +$sel->type_ok("cf_qa_freetext_$bug1_id", "thanks"); +$sel->click_ok("commit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Bugs processed"); +$sel->click_ok("link=bug $bug2_id"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_like(qr/^$bug2_id/); +$sel->value_is("cf_qa_freetext_$bug1_id", "thanks"); +$sel->selected_label_is("cf_qa_list_$bug1_id", "---"); +$sel->select_ok("cf_qa_list_$bug1_id", "label=storage"); +edit_bug($sel, $bug2_id); + +# Let's now test custom field visibility. + +go_to_admin($sel); +$sel->click_ok("link=Custom Fields"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Custom Fields"); +$sel->click_ok("link=cf_qa_list_$bug1_id"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Edit the Custom Field 'cf_qa_list_$bug1_id' (List$bug1_id)"); +$sel->select_ok("visibility_field_id", "label=Severity (bug_severity)"); +$sel->select_ok("visibility_values", "label=critical"); +$sel->click_ok("edit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Custom Field Updated"); + +go_to_bug($sel, $bug1_id); +$sel->is_element_present_ok("cf_qa_list_$bug1_id", "List$bug1_id is in the DOM of the page..."); +ok(!$sel->is_visible("cf_qa_list_$bug1_id"), "... but is not displayed with severity = 'normal'"); +$sel->select_ok("bug_severity", "major"); +ok(!$sel->is_visible("cf_qa_list_$bug1_id"), "... nor with severity = 'major'"); +$sel->select_ok("bug_severity", "critical"); +$sel->is_visible_ok("cf_qa_list_$bug1_id", "... but is visible with severity = 'critical'"); +edit_bug_and_return($sel, $bug1_id, $bug_summary); +$sel->is_visible_ok("cf_qa_list_$bug1_id"); + +go_to_bug($sel, $bug2_id); +$sel->is_visible_ok("cf_qa_list_$bug1_id"); +$sel->select_ok("bug_severity", "minor"); +ok(!$sel->is_visible("cf_qa_list_$bug1_id"), "List$bug1_id is not displayed with severity = 'minor'"); +edit_bug_and_return($sel, $bug2_id, $bug_summary2); +ok(!$sel->is_visible("cf_qa_list_$bug1_id"), "List$bug1_id is not displayed with severity = 'minor'"); + +# Add a new value which is only listed under some condition. + +go_to_admin($sel); +$sel->click_ok("link=Custom Fields"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Custom Fields"); +$sel->click_ok("link=cf_qa_list_$bug1_id"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Edit the Custom Field 'cf_qa_list_$bug1_id' (List$bug1_id)"); +$sel->select_ok("value_field_id", "label=Resolution (resolution)"); +$sel->click_ok("edit"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Custom Field Updated"); +$sel->click_ok("link=cf_qa_list_$bug1_id"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Edit the Custom Field 'cf_qa_list_$bug1_id' (List$bug1_id)"); +$sel->click_ok("link=Edit legal values for this field"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Select value for the 'List$bug1_id' (cf_qa_list_$bug1_id) field"); +$sel->click_ok("link=Add"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Add Value for the 'List$bug1_id' (cf_qa_list_$bug1_id) field"); +$sel->type_ok("value", "ghost"); +$sel->type_ok("sortkey", "500"); +$sel->select_ok("visibility_value_id", "label=FIXED"); +$sel->click_ok("id=create"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("New Field Value Created"); + +go_to_bug($sel, $bug1_id); +my @labels = $sel->get_select_options("cf_qa_list_$bug1_id"); +ok(grep(/^ghost$/, @labels), "ghost is in the DOM of the page..."); +my $disabled = $sel->get_attribute("v4_cf_qa_list_$bug1_id\@disabled"); +ok($disabled, "... but is not available for selection by default"); +$sel->select_ok("bug_status", "label=RESOLVED"); +$sel->select_ok("resolution", "label=FIXED"); +$sel->select_ok("cf_qa_list_$bug1_id", "label=ghost"); +edit_bug_and_return($sel, $bug1_id, $bug_summary); +$sel->selected_label_is("cf_qa_list_$bug1_id", "ghost"); + +# Delete an unused field value. + +go_to_admin($sel); +$sel->click_ok("link=Field Values"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Edit values for which field?"); +$sel->click_ok("link=List$bug1_id"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Select value for the 'List$bug1_id' (cf_qa_list_$bug1_id) field"); +$sel->click_ok("//a[contains(\@href, 'editvalues.cgi?action=del&field=cf_qa_list_$bug1_id&value=have%20fun%3F')]"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Delete Value 'have fun?' from the 'List$bug1_id' (cf_qa_list_$bug1_id) field"); +$sel->is_text_present_ok("Do you really want to delete this value?"); +$sel->click_ok("delete"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Field Value Deleted"); + +# This value cannot be deleted as it's in use. + +$sel->click_ok("//a[contains(\@href, 'editvalues.cgi?action=del&field=cf_qa_list_$bug1_id&value=storage')]"); +$sel->wait_for_page_to_load_ok(WAIT_TIME); +$sel->title_is("Delete Value 'storage' from the 'List$bug1_id' (cf_qa_list_$bug1_id) field"); +$sel->is_text_present_ok("There is 1 bug with this field value"); + +# Mark the