From 320c2c07b0e99f9c8ed81c76e65064f39a1eccbb Mon Sep 17 00:00:00 2001 From: Doug Bell Date: Fri, 12 Oct 2007 20:44:38 +0000 Subject: [PATCH] more tests plus a framework for making test generators --- t/Asset/File/Image/Photo/editSave.t | 94 +++++++++ t/Asset/File/Image/Photo/makeShortcut.t | 17 +- t/lib/WebGUI/Test/Maker.pm | 192 ++++++++++++++++++ t/lib/WebGUI/Test/Maker/HTML.pm | 250 ++++++++++++++++++++++++ t/lib/WebGUI/Test/Maker/Permission.pm | 207 ++++++++++++++++++++ 5 files changed, 752 insertions(+), 8 deletions(-) create mode 100644 t/Asset/File/Image/Photo/editSave.t create mode 100644 t/lib/WebGUI/Test/Maker.pm create mode 100644 t/lib/WebGUI/Test/Maker/HTML.pm create mode 100644 t/lib/WebGUI/Test/Maker/Permission.pm diff --git a/t/Asset/File/Image/Photo/editSave.t b/t/Asset/File/Image/Photo/editSave.t new file mode 100644 index 000000000..51bfbb6b1 --- /dev/null +++ b/t/Asset/File/Image/Photo/editSave.t @@ -0,0 +1,94 @@ +#------------------------------------------------------------------- +# WebGUI is Copyright 2001-2007 Plain Black Corporation. +#------------------------------------------------------------------- +# Please read the legal notices (docs/legal.txt) and the license +# (docs/license.txt) that came with this distribution before using +# this software. +#------------------------------------------------------------------- +# http://www.plainblack.com info@plainblack.com +#------------------------------------------------------------------- + +# The goal of this test is to test the editSave and +# processPropertiesFromFormPost methods. + +use FindBin; +use strict; +use lib "$FindBin::Bin/../../../../lib"; + +use Scalar::Util qw( blessed ); +use WebGUI::Test; +use WebGUI::Session; +use Test::More; +use WebGUI::Test::Maker::HTML; +use WebGUI::Asset::File::Image::Photo; + +#---------------------------------------------------------------------------- +# Init +my $session = WebGUI::Test->session; +my $node = WebGUI::Asset->getImportNode($session); +my $versionTag = WebGUI::VersionTag->getWorking($session); +$versionTag->set({name=>"Photo Test"}); +my $maker = WebGUI::Test::Maker::HTML->new; +my $gallery + = $node->addChild({ + className => "WebGUI::Asset::Wobject::PhotoGallery", + }); +my $album + = $gallery->addChild({ + className => "WebGUI::Asset::Wobject::PhotoAlbum", + }); +my $photo + = $gallery->addChild({ + className => "WebGUI::Asset::File::Image::Photo", + }); + +#---------------------------------------------------------------------------- +# Cleanup +END { + $versionTag->rollback(); +} + +#---------------------------------------------------------------------------- +# Tests +plan tests => 0; + +#---------------------------------------------------------------------------- +# Test permissions + +# Edit an existing photo +$maker->prepare({ + object => $photo, + method => "www_edit", + userId => "1", + test_privilege => "insufficient", +})->run; + +# Save a new photo +$maker->prepare({ + object => $photo, + method => "www_editSave", + userId => "1", + test_privilege => "insufficient", +})->run; + +#---------------------------------------------------------------------------- +# Test processPropertiesFromFormPost errors +# TODO: This test should use i18n. +# TODO: This error / test should occur in File, not Photo +$maker->prepare({ + object => $album + method => "www_editSave", + formParams => { + + + }, + test_regex => [ + qr/You must select a file/, + qr/You must enter a title/, + ], +})->run; + +#---------------------------------------------------------------------------- +# Test editSave success result + +#---------------------------------------------------------------------------- diff --git a/t/Asset/File/Image/Photo/makeShortcut.t b/t/Asset/File/Image/Photo/makeShortcut.t index 09bc5e075..adbb7dd75 100644 --- a/t/Asset/File/Image/Photo/makeShortcut.t +++ b/t/Asset/File/Image/Photo/makeShortcut.t @@ -19,6 +19,7 @@ use Scalar::Util qw( blessed ); use WebGUI::Test; use WebGUI::Session; use Test::More; +use WebGUI::Test::Maker::HTML; use WebGUI::Asset::File::Image::Photo; #---------------------------------------------------------------------------- @@ -27,6 +28,7 @@ my $session = WebGUI::Test->session; my $node = WebGUI::Asset->getImportNode($session); my $versionTag = WebGUI::VersionTag->getWorking($session); $versionTag->set({name=>"Photo Test"}); +my $maker = WebGUI::Test::Maker::HTML->new; my $otherParent = $node->addChild({ className => "WebGUI::Asset::Wobject::Layout", @@ -109,14 +111,13 @@ is_deeply( #---------------------------------------------------------------------------- # www_makeShortcut is only available to those who can edit the photo -my $html = WebGUI::Test->getPage($photo, "www_makeShortcut", { - userId => 1, - }); - -like( - $html, qr/permission denied/i, - "www_makeShortcut is not allowed to those who can't edit the photo", -); +$maker->prepare({ + object => $photo, + method => "www_makeShortcut", + userId => 1, + test_privilege => "insufficient", +}); +$maker->run; #---------------------------------------------------------------------------- # www_makeShortcut diff --git a/t/lib/WebGUI/Test/Maker.pm b/t/lib/WebGUI/Test/Maker.pm new file mode 100644 index 000000000..f3463f38f --- /dev/null +++ b/t/lib/WebGUI/Test/Maker.pm @@ -0,0 +1,192 @@ +package WebGUI::Test::Maker; + +use Test::More; + + +=head1 NAME + +WebGUI::Test::Maker + +=head1 SYNOPSIS + + use Test::More; + use WebGUI::Test::Maker; + + my $maker = WebGUI::Test::Maker->new(); + + $maker->set( test => sub { ... } ); + $maker->set( plan_per_test => 2 ); + + $maker->prepare({ + title => "Test something", + args => [ ... ], + }); + + plan tests => $maker->plan; + + $maker->run; + +=head1 DESCRIPTION + +Test generator for generating repeatable tests. + +Set a subroutine that runs some tests and run it over and over with +different arguments. + +=head1 DEPENDS + +This module depends on + +=over 4 + +=item * + +Test::More + +=back + +=head1 METHODS + +=head2 new + +Create a new WebGUI::Test::Maker object. + +=cut + +sub new { + my $class = shift; + my $self = {}; + + return bless $self, $class; +} + +#---------------------------------------------------------------------------- + +=head2 get + +Get a setting. Set L for a list of settings. + +=cut + +sub get { + my $self = shift; + my $key = shift; + + return $self->{_settings}->{$key}; +} + +#---------------------------------------------------------------------------- + +=head2 plan + +Returns the number of tests currently prepared. This module is so generic +that you must set the C value before calling this method. + +=cut + +sub plan { + my $self = shift; + + return $self->plan_per_test * @{$self->{_tests}}; +} + +#---------------------------------------------------------------------------- + +=head2 plan_per_test + +Returns the current value of the C setting. + +=cut + +sub plan_per_test { + return $self->get("plan_per_test"); +} + +#---------------------------------------------------------------------------- + +=head2 prepare + +Prepare a test(s). Returns the object for convenience. The following keys +are optional: + +=over 4 + +=item args + +An array reference of arguments to the subroutine. + +=back + +There are no required arguments. + +=cut + +sub prepare { + my $self = shift; + my @tests = @_; + my $test_num = 0; + for my $test (@tests) { + $test_num++; + + push @{$self->{_tests}}, $test; + } + + return $self; +} + +#---------------------------------------------------------------------------- + +=head2 run + +Run the tests we've prepared and delete them as we run them. + +=cut + +sub run { + my $self = shift; + + while (my $test = shift @{ $self->{_tests} }) { + my $sub = $self->get("test"); + if ($test->{args}) { + $sub->(@{ $test->{args} }); + } + else { + $sub->(); + } + } +} + +#---------------------------------------------------------------------------- + +=head2 set + +Set a setting. + +Available settings: + +=over 4 + +=item test + +A subref that runs some tests. The first argument to this subref will be the +WebGUI::Test::Maker object. The second and subsequent arguments will be the +C key from the prepared test. + +=item plan_per_test + +Set the number of tests that each C sub runs to be used to plan the +number of total tests that will be run. + +=back + +=cut + +sub set { + my $self = shift; + my $key = shift; + my $value = shift; + + $self->{_setting}->{$key} = $value; +} + +1; diff --git a/t/lib/WebGUI/Test/Maker/HTML.pm b/t/lib/WebGUI/Test/Maker/HTML.pm new file mode 100644 index 000000000..5607ac546 --- /dev/null +++ b/t/lib/WebGUI/Test/Maker/HTML.pm @@ -0,0 +1,250 @@ +package WebGUI::Test::Maker::HTML; + +use base 'WebGUI::Test::Maker'; +use Scalar::Util qw( blessed ); +use Test::More; + + +=head1 NAME + +WebGUI::Test::Maker::HTML -- Test::Maker subclass for WebGUI HTMLs + +=head1 SYNOPSIS + + use Test::More; + use WebGUI::Test::Maker::HTML; + + my $maker = WebGUI::Test::Maker::HTML->new(); + + $maker->prepare({ + object => $object, + method => "www_editSave", + user => WebGUI::User->new, + userId => "userId", + formParams => { ... }, + uploads => { ... }, + + # Test for a WebGUI::Session::Privilege page + test_privilege => "permission", + + # Test for some regular expressions + test_regex => [ qr/../, qr/.../, ... ], + }); + + plan tests => $maker->plan; + + $maker->run; + +=head1 DESCRIPTION + +This Test::Maker subclass tests the HTML output by WebGUI methods in a +variety of ways. + +Uses WebGUI::Test->getPage to get the HTML for a page, and so is limited +to whatever C can access. + +=head1 TODO + +Provide a method to give a proper HTML::Parser to test with. + +Provide a method to test that a certain page was created with a certain +template. + +=head1 DEPENDS + +This module depends on + +=over 4 + +=item * + +Test::More + +=back + +=head1 METHODS + +=head2 new + +Create a new WebGUI::Test::Maker::HTML object. + +=head2 get + +Get a setting. Set L for a list of settings. + +#---------------------------------------------------------------------------- + +=head2 plan + +This module plans as follows: + + - 1 and only 1 test for any test_privilege test + - 1 test for each member of a test_regex test + +=cut + +sub plan { + my $self = shift; + my $plan; + + for my $test ( @{ $self->{_tests} } ) { + if ($test->{test_privilege}) { + $plan++; + next; + } + if ($test->{test_regex}) { + $plan += @{$test->{test_regex}}; + } + } + + return $plan; +} + +#---------------------------------------------------------------------------- + +=head2 plan_per_test + +Returns undef. There is no way to pre-calculate how many tests this will run + +=cut + +sub plan_per_test { + return undef; +} + +#---------------------------------------------------------------------------- + +=head2 prepare + +Prepare a test(s). Returns the object for convenience. The following keys +are required: + +=over 4 + +=item object + +An instanciated object to work on. + +=item method + +The permissions method to test + +=back + +At least one of the following keys are required: + +=over 4 + +=item test_privilege + +Tests for a WebGUI::Session::Privilege response. Valid values for this key +are: adminOnly, insufficient, noAccess, notMember, vitalComponent + +=item test_regex + +Tests for some regular expressions. This key must be an array reference of +qr(). + +=back + +The following key are optional: + +=over 4 + +=item user + +A WebGUI::User object to use for the test. + +=item userId + +A user ID to make a WebGUI::User object to use for the test + +=item formParams + +A hash reference of form parameters to use for the test + +=item uploads + +A hash reference of file uploads to use for the test + +=back + +=cut + +sub prepare { + my $self = shift; + my @tests = @_; + my $test_num = 0; + for my $test (@tests) { + $test_num++; + + croak("Couldn't prepare: Test $test_num has no object") + unless $test->{object}; + croak("Couldn't prepare: Test $test_num has no method") + unless $test->{method}; + croak("Couldn't prepare: Test $test_num has test (test_privilege or test_regex)") + unless $test->{test_privilege} || $test->{test_regex}; + croak("Couldn't prepare: Test $test_num, test_regex is not an array reference") + if $test->{test_regex} && ref $test->{test_regex} ne "ARRAY"; + croak("Couldn't prepare: Test $test_num, $test->{test_privilege} is not a valid test_privilege value (adminOnly, insufficient, noAccess, notMember, vitalComponent)") + if $test->{test_privilege} && $test->{test_privilege} =~ m/adminOnly|insufficient|noAccess|notMember|vitalComponent/; + + push @{$self->{_tests}}, $test; + } + + return $self; +} + +#---------------------------------------------------------------------------- + +=head2 run + +Run the tests we've prepared and delete them as we run them. + +=cut + +sub run { + my $self = shift; + + while (my $test = shift @{ $self->{_tests} }) { + my $o = $test->{object}; + my $m = $test->{method}; + + # Get the HTML + my $opts = {}; + for my $key (qw{ }) { + $opts->{$key} = $test->{$key}; + } + + my $html + = WebGUI::Test->getPage( $o, $m, $opts ); + + # Run the tests + if ($test->{test_privilege}) { + my $priv_method = $test->{test_privilege}; + my $test = $o->session->privilege->$priv_method(); + + like( $html, $test, "$m contains privilege message $priv_method for object " . blessed $o ); + + next; + } + + if ($test->{test_regex}) { + for my $regex ( @{ $test->{test_regex} } ) { + like( $html, $regex, "$m contains $regex for object " . blessed $o ); + } + } + } +} + +#---------------------------------------------------------------------------- + +=head2 set + +Set a setting. + +Currently this module has no settings + +=cut + +1; diff --git a/t/lib/WebGUI/Test/Maker/Permission.pm b/t/lib/WebGUI/Test/Maker/Permission.pm new file mode 100644 index 000000000..926b82d24 --- /dev/null +++ b/t/lib/WebGUI/Test/Maker/Permission.pm @@ -0,0 +1,207 @@ +package WebGUI::Test::Maker::Permission; + +use base 'WebGUI::Test::Maker'; +use Scalar::Util qw( blessed ); +use Test::More; + + +=head1 NAME + +WebGUI::Test::Maker::Permission -- Test::Maker subclass for WebGUI Permissions + +=head1 SYNOPSIS + + use Test::More; + use WebGUI::Test::Maker::Permission; + + my $maker = WebGUI::Test::Maker::Permission->new(); + + $maker->prepare({ + object => WebGUI::Asset->new, + method => "canView", + pass => [userId, userId], + fail => [userId, userId], + }); + + plan tests => $maker->plan; + + $maker->run; + +=head1 DESCRIPTION + +Test generator for testing WebGUI permissions. WebGUI permissions subroutines +take a single argument (a userId), or they use the default user from the +current session. They return true if the user has permission, or false +otherwise. + +This module tests permissions subroutines by running a list of userIds that +should either pass or fail the permissions. + +=head1 DEPENDS + +This module depends on + +=over 4 + +=item * + +Test::More + +=back + +=head1 METHODS + +=head2 new + +Create a new WebGUI::Test::Maker::Permission object. + +=head2 get + +Get a setting. Set L for a list of settings. + +#---------------------------------------------------------------------------- + +=head2 plan + +Returns the number of tests currently prepared. This module runs two tests +for each userId in either the C or C keys of the C +hash reference. + +=cut + +sub plan { + my $self = shift; + my $plan; + + for my $test ( @{$self->{_tests}} ) { + if ($test->{pass}) { + $plan += @{$test->{pass}} * 2; + } + if ($test->{fail}) { + $plan += @{$test->{fail}} * 2; + } + } + + return $plan; +} + +#---------------------------------------------------------------------------- + +=head2 plan_per_test + +Returns undef. There is no way to pre-calculate how many tests this will run + +=cut + +sub plan_per_test { + return undef; +} + +#---------------------------------------------------------------------------- + +=head2 prepare + +Prepare a test(s). Returns the object for convenience. The following keys +are required: + +=over 4 + +=item object + +An instanciated object to work on. + +=item method + +The permissions method to test + +=item pass + +An array reference of userIds that should pass the permissions test. + +=item fail + +An array reference of userIds that should fail the permissions test. + +=back + +There are no optional parameters. + +=cut + +sub prepare { + my $self = shift; + my @tests = @_; + my $test_num = 0; + for my $test (@tests) { + $test_num++; + + croak("Couldn't prepare: Test $test_num has no object") + unless $test->{object}; + croak("Couldn't prepare: Test $test_num has no method") + unless $test->{method}; + croak("Couldn't prepare: Test $test_num has no pass/fail") + unless $test->{pass} || $test->{fail}; + croak("Couldn't prepare: Test $test_num, pass is not an array reference") + if $test->{pass} && ref $test->{pass} ne "ARRAY"; + croak("Couldn't prepare: Test $test_num, fail is not an array reference") + if $test->{fail} && ref $test->{fail} ne "ARRAY"; + + push @{$self->{_tests}}, $test; + } + + return $self; +} + +#---------------------------------------------------------------------------- + +=head2 run + +Run the tests we've prepared and delete them as we run them. + +=cut + +sub run { + my $self = shift; + + while (my $test = shift @{ $self->{_tests} }) { + my $o = $test->{object}; + my $m = $test->{method}; + + if ($test->{pass}) { + for my $userId (@{$test->{pass}}) { + # Test the userId parameter + ok( $o->$m($userId), "$userId passes $m check for " . blessed $o ); + + # Test the default session user + my $oldUser = $o->session->user; + $o->session->user( WebGUI::User->new($o->session, $userId) ); + ok( $o->$m(), "$userId passes $m check using default user for " . blessed $o ); + $o->session->user($oldUser); + } + } + if ($test->{fail}) { + for my $userId (@{$test->{fail}}) { + # Test the userId parameter + ok( !($o->$m($userId)), "$userId fails $m check for " . blessed $o ); + + # Test the default session user + my $oldUser = $o->session->user; + $o->session->user( WebGUI::User->new($o->session, $userId) ); + ok( !($o->$m()), "$userId fails $m check using default user for " . blessed $o ); + $o->session->user($oldUser); + } + } + } +} + +#---------------------------------------------------------------------------- + +=head2 set + +Set a setting. + +Currently this module has no settings + +=cut + +1;