summaryrefslogtreecommitdiffstats
path: root/qa/t/lib/QA
diff options
context:
space:
mode:
Diffstat (limited to 'qa/t/lib/QA')
-rw-r--r--qa/t/lib/QA/REST.pm61
-rw-r--r--qa/t/lib/QA/RPC.pm454
-rw-r--r--qa/t/lib/QA/RPC/JSONRPC.pm192
-rw-r--r--qa/t/lib/QA/RPC/XMLRPC.pm2
-rw-r--r--qa/t/lib/QA/Tests.pm114
-rw-r--r--qa/t/lib/QA/Util.pm593
6 files changed, 746 insertions, 670 deletions
diff --git a/qa/t/lib/QA/REST.pm b/qa/t/lib/QA/REST.pm
index f900cc352..3d37e2277 100644
--- a/qa/t/lib/QA/REST.pm
+++ b/qa/t/lib/QA/REST.pm
@@ -19,43 +19,46 @@ use QA::Util;
use parent qw(LWP::UserAgent Exporter);
@QA::REST::EXPORT = qw(
- MUST_FAIL
- get_rest_client
+ MUST_FAIL
+ get_rest_client
);
use constant MUST_FAIL => 1;
sub get_rest_client {
- my $rest_client = LWP::UserAgent->new( ssl_opts => { verify_hostname => 0 } );
- bless($rest_client, 'QA::REST');
- my $config = $rest_client->{bz_config} = get_config();
- $rest_client->{bz_url} = $config->{browser_url} . '/' . $config->{bugzilla_installation} . '/rest/';
- $rest_client->{bz_default_headers} = {'Accept' => 'application/json', 'Content-Type' => 'application/json'};
- return $rest_client;
+ my $rest_client = LWP::UserAgent->new(ssl_opts => {verify_hostname => 0});
+ bless($rest_client, 'QA::REST');
+ my $config = $rest_client->{bz_config} = get_config();
+ $rest_client->{bz_url}
+ = $config->{browser_url} . '/' . $config->{bugzilla_installation} . '/rest/';
+ $rest_client->{bz_default_headers}
+ = {'Accept' => 'application/json', 'Content-Type' => 'application/json'};
+ return $rest_client;
}
sub bz_config { return $_[0]->{bz_config}; }
sub call {
- my ($self, $method, $data, $http_verb, $expect_to_fail) = @_;
- $http_verb = lc($http_verb || 'GET');
- $data //= {};
-
- my %args = %{ $self->{bz_default_headers} };
- # We do not pass the API key in the URL, so that it's not logged by the web server.
- if ($http_verb eq 'get' && $data->{api_key}) {
- $args{'X-BUGZILLA-API-KEY'} = $data->{api_key};
- }
- elsif ($http_verb ne 'get') {
- $args{Content} = encode_json($data);
- }
-
- my $response = $self->$http_verb($self->{bz_url} . $method, %args);
- my $res = decode_json($response->decoded_content);
- if ($response->is_success xor $expect_to_fail) {
- return $res;
- }
- else {
- die 'error ' . $res->{code} . ': ' . $res->{message} . "\n";
- }
+ my ($self, $method, $data, $http_verb, $expect_to_fail) = @_;
+ $http_verb = lc($http_verb || 'GET');
+ $data //= {};
+
+ my %args = %{$self->{bz_default_headers}};
+
+# We do not pass the API key in the URL, so that it's not logged by the web server.
+ if ($http_verb eq 'get' && $data->{api_key}) {
+ $args{'X-BUGZILLA-API-KEY'} = $data->{api_key};
+ }
+ elsif ($http_verb ne 'get') {
+ $args{Content} = encode_json($data);
+ }
+
+ my $response = $self->$http_verb($self->{bz_url} . $method, %args);
+ my $res = decode_json($response->decoded_content);
+ if ($response->is_success xor $expect_to_fail) {
+ return $res;
+ }
+ else {
+ die 'error ' . $res->{code} . ': ' . $res->{message} . "\n";
+ }
}
diff --git a/qa/t/lib/QA/RPC.pm b/qa/t/lib/QA/RPC.pm
index 4053c4dfe..f1b44eea8 100644
--- a/qa/t/lib/QA/RPC.pm
+++ b/qa/t/lib/QA/RPC.pm
@@ -16,9 +16,9 @@ use Storable qw(dclone);
use Test::More;
sub bz_config {
- my $self = shift;
- $self->{bz_config} ||= QA::Util::get_config();
- return $self->{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.
@@ -29,12 +29,12 @@ sub bz_get_mode { return 0 }
# 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};
+ 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} }
@@ -43,240 +43,258 @@ sub _bz_clear_credentials { delete $_[0]->{_bz_credentials} }
################################
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};
+ my ($self, $user) = @_;
+ my $username = $self->bz_config->{"${user}_user_login"};
+ my $password = $self->bz_config->{"${user}_user_passwd"};
+
+ if ($self->bz_get_mode) {
+ $self->_bz_credentials($username, $password);
+ return;
+ }
+
+ my $call = $self->bz_call_success('User.login',
+ {login => $username, password => $password});
+ cmp_ok($call->result->{id}, 'gt', 0, $self->TYPE . ": Logged in as $user");
+ $self->{_bz_credentials}->{token} = $call->result->{token};
}
sub bz_call_success {
- my ($self, $method, $orig_args, $test_name) = @_;
- my $args = $orig_args ? dclone($orig_args) : {};
-
- if ($self->bz_get_mode and $method eq 'User.logout') {
- $self->_bz_clear_credentials();
- return;
- }
-
- my $call;
- # Under XMLRPC::Lite, if we pass undef as the second argument,
- # it sends a single param <value />, which shows up as an
- # empty string on the Bugzilla side.
- if ($self->{_bz_credentials}->{token}) {
- $args->{Bugzilla_token} = $self->{_bz_credentials}->{token};
- }
-
- if (scalar keys %$args) {
- $call = $self->call($method, $args);
- }
- else {
- $call = $self->call($method);
- }
- $test_name ||= "$method returned successfully";
- $self->_handle_undef_response($test_name) if !$call;
- ok(!$call->fault, $self->TYPE . ": $test_name")
- or diag($call->faultstring);
-
- if ($method eq 'User.logout') {
- delete $self->{_bz_credentials}->{token};
- }
- return $call;
+ my ($self, $method, $orig_args, $test_name) = @_;
+ my $args = $orig_args ? dclone($orig_args) : {};
+
+ if ($self->bz_get_mode and $method eq 'User.logout') {
+ $self->_bz_clear_credentials();
+ return;
+ }
+
+ my $call;
+
+ # Under XMLRPC::Lite, if we pass undef as the second argument,
+ # it sends a single param <value />, which shows up as an
+ # empty string on the Bugzilla side.
+ if ($self->{_bz_credentials}->{token}) {
+ $args->{Bugzilla_token} = $self->{_bz_credentials}->{token};
+ }
+
+ if (scalar keys %$args) {
+ $call = $self->call($method, $args);
+ }
+ else {
+ $call = $self->call($method);
+ }
+ $test_name ||= "$method returned successfully";
+ $self->_handle_undef_response($test_name) if !$call;
+ ok(!$call->fault, $self->TYPE . ": $test_name") or diag($call->faultstring);
+
+ if ($method eq 'User.logout') {
+ delete $self->{_bz_credentials}->{token};
+ }
+ return $call;
}
sub bz_call_fail {
- my ($self, $method, $orig_args, $faultstring, $test_name) = @_;
- my $args = $orig_args ? dclone($orig_args) : {};
-
- if ($self->{_bz_credentials}->{token}) {
- $args->{Bugzilla_token} = $self->{_bz_credentials}->{token};
- }
-
- $test_name ||= "$method failed (as intended)";
- my $call = $self->call($method, $args);
- $self->_handle_undef_response($test_name) if !$call;
- ok($call->fault, $self->TYPE . ": $test_name")
- or diag("Returned: " . Dumper($call->result));
- if (defined $faultstring) {
- cmp_ok(trim($call->faultstring), '=~', $faultstring,
- $self->TYPE . ": Got correct fault for $method");
- }
- ok($call->faultcode
- && (($call->faultcode < 32000 && $call->faultcode > -32000)
- # Fault codes 32610 and above are OK because they are errors
- # that we expect and test for sometimes.
- || $call->faultcode >= 32610),
- $self->TYPE . ': Fault code is set properly')
- or diag("Code: " . $call->faultcode
- . " Message: " . $call->faultstring);
-
- return $call;
+ 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;
+ 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;
+ 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 _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);
+ 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);
- }
- }
+ 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;
+ $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");
- }
+ 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;
diff --git a/qa/t/lib/QA/RPC/JSONRPC.pm b/qa/t/lib/QA/RPC/JSONRPC.pm
index 4175b10fc..1e43e9eaf 100644
--- a/qa/t/lib/QA/RPC/JSONRPC.pm
+++ b/qa/t/lib/QA/RPC/JSONRPC.pm
@@ -11,24 +11,26 @@ 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');
- }
+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';
+ my ($self) = @_;
+ return $self->bz_get_mode ? 'JSON-RPC GET' : 'JSON-RPC';
}
#################################
@@ -36,85 +38,88 @@ sub TYPE {
#################################
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(@_);
+ 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};
+ 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};
+ my ($self, $value) = @_;
+ $self->{bz_callback} = $value if @_ > 1;
+ return $self->{bz_callback};
}
sub call {
- my $self = shift;
- my ($method, $args) = @_;
- my %params = ( method => $method );
- $params{params} = $args ? [$args] : [];
-
- my $config = $self->bz_config;
- my $url = $config->{browser_url} . "/"
- . $config->{bugzilla_installation} . "/jsonrpc.cgi";
- my $result;
- if ($self->bz_get_mode) {
- my $method_escaped = uri_escape($method);
- $url .= "?method=$method_escaped";
- if (my $cred = $self->_bz_credentials) {
- $args->{Bugzilla_login} = $cred->{user}
- if !exists $args->{Bugzilla_login};
- $args->{Bugzilla_password} = $cred->{pass}
- if !exists $args->{Bugzilla_password};
- }
- if ($args) {
- my $params_json = $self->json->encode($args);
- my $params_escaped = uri_escape($params_json);
- $url .= "&params=$params_escaped";
- }
- if ($self->version eq '1.1') {
- $url .= "&version=1.1";
- }
- my $callback = delete $args->{callback};
- if (defined $callback) {
- $self->_bz_callback($callback);
- $url .= "&callback=" . uri_escape($callback);
- }
- $result = $self->SUPER::call($url);
+ 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};
}
- else {
- $result = $self->SUPER::call($url, \%params);
+ if ($args) {
+ my $params_json = $self->json->encode($args);
+ my $params_escaped = uri_escape($params_json);
+ $url .= "&params=$params_escaped";
}
-
- if ($result) {
- bless $result, 'QA::RPC::JSONRPC::ReturnObject';
+ 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);
}
- return $result;
+ $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;
+ 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;
@@ -123,13 +128,13 @@ 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);
- }
+ 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);
+ }
}
#################################
@@ -137,8 +142,8 @@ BEGIN {
#################################
sub faultstring { $_[0]->{content}->{error}->{message} }
-sub faultcode { $_[0]->{content}->{error}->{code} }
-sub fault { $_[0]->is_error }
+sub faultcode { $_[0]->{content}->{error}->{code} }
+sub fault { $_[0]->is_error }
1;
@@ -151,18 +156,19 @@ use base qw(LWP::UserAgent);
########################################
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;
+ 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'};
+ 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
index d88d4092e..6e63852eb 100644
--- a/qa/t/lib/QA/RPC/XMLRPC.pm
+++ b/qa/t/lib/QA/RPC/XMLRPC.pm
@@ -11,7 +11,7 @@ package QA::RPC::XMLRPC;
use strict;
use base qw(QA::RPC XMLRPC::Lite);
-use constant TYPE => 'XML-RPC';
+use constant TYPE => 'XML-RPC';
use constant DATETIME_REGEX => qr/^\d{8}T\d\d:\d\d:\d\d$/;
1;
diff --git a/qa/t/lib/QA/Tests.pm b/qa/t/lib/QA/Tests.pm
index 86fc06ad1..3d53cefcc 100644
--- a/qa/t/lib/QA/Tests.pm
+++ b/qa/t/lib/QA/Tests.pm
@@ -11,96 +11,108 @@ package QA::Tests;
use strict;
use base qw(Exporter);
our @EXPORT_OK = qw(
- PRIVATE_BUG_USER
- STANDARD_BUG_TESTS
- bug_tests
- create_bug_fields
+ PRIVATE_BUG_USER
+ STANDARD_BUG_TESTS
+ bug_tests
+ create_bug_fields
);
-use constant INVALID_BUG_ID => -1;
+use constant INVALID_BUG_ID => -1;
use constant INVALID_BUG_ALIAS => 'aaaaaaa12345';
-use constant PRIVATE_BUG_USER => 'QA_Selenium_TEST';
+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 => 'https://www.bugzilla.org/',
- target_milestone => 'AnotherMS1',
+ '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 => 'https://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;
+ 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] },
+ 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] },
+ {
+ args => {ids => [$public_id]},
test => 'Logged-out user can access a public bug.',
},
- { args => { ids => [INVALID_BUG_ID] },
+ {
+ args => {ids => [INVALID_BUG_ID]},
error => "It does not seem like bug number",
test => 'Passing invalid bug id returns error "Invalid Bug ID"',
},
- { args => { ids => [undef] },
+ {
+ 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] },
+ {
+ 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] },
+ {
+ 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] },
+ {
+ user => 'unprivileged',
+ args => {ids => [$public_id]},
test => 'User without privs can access a public bug',
},
- { user => 'admin',
- args => { ids => [$public_id] },
+ {
+ user => 'admin',
+ args => {ids => [$public_id]},
test => 'Admin can access a public bug.',
},
- { user => PRIVATE_BUG_USER,
- args => { ids => [$private_id] },
+ {
+ 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] },
+ {
+ 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');
diff --git a/qa/t/lib/QA/Util.pm b/qa/t/lib/QA/Util.pm
index bf9151fee..fd584975a 100644
--- a/qa/t/lib/QA/Util.pm
+++ b/qa/t/lib/QA/Util.pm
@@ -22,72 +22,74 @@ use URI::QueryParam;
# 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)";
+ 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
- screenshot_page
-
- get_selenium
- get_rpc_clients
- check_page_load
-
- WAIT_TIME
- CHROME_MODE
+ 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
+ screenshot_page
+
+ get_selenium
+ get_rpc_clients
+ check_page_load
+
+ WAIT_TIME
+ CHROME_MODE
);
# How long we wait for pages to load.
use constant WAIT_TIME => 60000;
-use constant CONF_FILE => $ENV{BZ_QA_CONF_FILE} // "../config/selenium_test.conf";
+use constant CONF_FILE => $ENV{BZ_QA_CONF_FILE}
+ // "../config/selenium_test.conf";
use constant CHROME_MODE => 1;
-use constant NDASH => chr(0x2013);
+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));
+ 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;
+ 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;
+ my ($toencode) = (@_);
+ $toencode =~ s/([^a-zA-Z0-9_\-.])/uc sprintf("%%%02x",ord($1))/eg;
+ return $toencode;
}
###################
@@ -95,67 +97,73 @@ sub url_quote {
###################
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': $!$@";
- my $uri = URI->new($config->{browser_url});
- if (my $ip_packed = gethostbyname($uri->host)) {
- my $ip = inet_ntoa($ip_packed);
- $uri->host($ip);
- $config->{browser_ip_url} = "$uri";
- }
- else {
- die "unable to find ip for $config->{browser_url}\n";
- }
- return $config;
+
+ # read the test configuration file
+ my $conf_file = CONF_FILE;
+ my $config = do($conf_file)
+ or die "can't read configuration '$conf_file': $!$@";
+ my $uri = URI->new($config->{browser_url});
+ if (my $ip_packed = gethostbyname($uri->host)) {
+ my $ip = inet_ntoa($ip_packed);
+ $uri->host($ip);
+ $config->{browser_ip_url} = "$uri";
+ }
+ else {
+ die "unable to find ip for $config->{browser_url}\n";
+ }
+ return $config;
}
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);
+ 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);
+ 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;
+ 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);
+ my ($xmlrpc, $config) = get_xmlrpc_client();
+ my $jsonrpc = get_jsonrpc_client();
+ my $jsonrpc_get = get_jsonrpc_client('GET');
+ return ($config, $xmlrpc, $jsonrpc, $jsonrpc_get);
}
################################
@@ -163,182 +171,210 @@ sub get_rpc_clients {
################################
sub go_to_home {
- my ($sel, $config) = @_;
- $sel->open_ok("/$config->{bugzilla_installation}/", undef, "Go to the home page");
- $sel->set_speed(500);
- $sel->title_is("Bugzilla Main Page");
+ my ($sel, $config) = @_;
+ $sel->open_ok("/$config->{bugzilla_installation}/",
+ undef, "Go to the home page");
+ $sel->set_speed(500);
+ $sel->title_is("Bugzilla Main Page");
}
sub screenshot_page {
- my ($sel, $filename) = @_;
- open my $fh, '>:raw', $filename or die "unable to write $filename: $!";
- binmode $fh;
- print $fh decode_base64($sel->capture_entire_page_screenshot_to_string());
- close $fh;
+ my ($sel, $filename) = @_;
+ open my $fh, '>:raw', $filename or die "unable to write $filename: $!";
+ binmode $fh;
+ print $fh decode_base64($sel->capture_entire_page_screenshot_to_string());
+ close $fh;
}
# Go to the home/login page and log in.
sub log_in {
- my ($sel, $config, $user) = @_;
-
- $sel->open_ok("/$config->{bugzilla_installation}/login", undef, "Go to the home page");
- $sel->title_is("Log in to Bugzilla");
- $sel->type_ok("Bugzilla_login", $config->{"${user}_user_login"}, "Enter $user login name");
- $sel->type_ok("Bugzilla_password", $config->{"${user}_user_passwd"}, "Enter $user password");
- $sel->click_ok("log_in", undef, "Submit credentials");
- $sel->wait_for_page_to_load(WAIT_TIME);
- $sel->title_is("Bugzilla Main Page", "User is logged in");
+ my ($sel, $config, $user) = @_;
+
+ $sel->open_ok("/$config->{bugzilla_installation}/login",
+ undef, "Go to the home page");
+ $sel->title_is("Log in to Bugzilla");
+ $sel->type_ok(
+ "Bugzilla_login",
+ $config->{"${user}_user_login"},
+ "Enter $user login name"
+ );
+ $sel->type_ok(
+ "Bugzilla_password",
+ $config->{"${user}_user_passwd"},
+ "Enter $user password"
+ );
+ $sel->click_ok("log_in", 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;
+ 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");
+ $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) = @_;
- my $config = get_config();
-
- $classification ||= "Unclassified";
- $sel->click_ok('//*[@class="link-file"]//a', undef, "Go create a new bug");
+ my ($sel, $product, $classification) = @_;
+ my $config = get_config();
+
+ $classification ||= "Unclassified";
+ $sel->click_ok('//*[@class="link-file"]//a', 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);
- 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("/" . $config->{bugzilla_installation} . "/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"]');
- }
+ $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(
+ "/"
+ . $config->{bugzilla_installation}
+ . "/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;
+ 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");
+ 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");
+ 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->submit("header-search");
- $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);
+ my ($sel, $bug_id) = @_;
+
+ $sel->type_ok("quicksearch_top", $bug_id);
+ $sel->submit("header-search");
+ $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;
+ 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");
+ $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");
+ 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);
- 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");
+ }
+ 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");
+ 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('//*[@class="link-search"]//a');
+ my $sel = shift;
+
+ $sel->click_ok('//*[@class="link-search"]//a');
+ $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);
- 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");
+ }
+ $sel->title_is("Search for bugs", "Display the Advanced search form");
}
# $params is a hashref of the form:
@@ -354,74 +390,75 @@ sub open_advanced_search_page {
# 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: General");
- my $last_section = "General";
-
- 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 ($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: General");
+ my $last_section = "General";
+
+ 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");
}
- 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);
- }
+ else {
+ ok(0, "Unknown parameter type: $type");
}
- $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");
+ }
+ 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");
+ }
}
my @ANY_KEYS = qw( t token );
sub check_page_load {
- my ($sel, $wait, $expected) = @_;
- my $expected_uri = URI->new($expected);
- $sel->wait_for_page_to_load_ok($wait);
- my $uri = URI->new($sel->get_location);
-
- foreach my $u ($expected_uri, $uri) {
- $u->host('HOSTNAME');
- foreach my $any_key (@ANY_KEYS) {
- if ($u->query_param($any_key)) {
- $u->query_param($any_key => '__ANYTHING__');
- }
- }
+ my ($sel, $wait, $expected) = @_;
+ my $expected_uri = URI->new($expected);
+ $sel->wait_for_page_to_load_ok($wait);
+ my $uri = URI->new($sel->get_location);
+
+ foreach my $u ($expected_uri, $uri) {
+ $u->host('HOSTNAME');
+ foreach my $any_key (@ANY_KEYS) {
+ if ($u->query_param($any_key)) {
+ $u->query_param($any_key => '__ANYTHING__');
+ }
}
+ }
- if ($expected_uri->query_param('id')) {
- if ($expected_uri->query_param('id') eq '__BUG_ID__') {
- $uri->query_param('id' => '__BUG_ID__');
- }
+ if ($expected_uri->query_param('id')) {
+ if ($expected_uri->query_param('id') eq '__BUG_ID__') {
+ $uri->query_param('id' => '__BUG_ID__');
}
- my ($pkg, $file, $line) = caller;
- is($uri, $expected_uri, "checking location on $file line $line");
+ }
+ my ($pkg, $file, $line) = caller;
+ is($uri, $expected_uri, "checking location on $file line $line");
}
1;