Skip to content

Commit

Permalink
Item13897: PlackTestCase is finished.
Browse files Browse the repository at this point in the history
This is another and hopefully the last megacommit to this branch. It may
have impact on overall code stability of this branch. I'm sorry for that
but to write those three words in the commit subject took a bit more than
just few changes. Next time a branch will be used.

With this commit I consider PlackTestCase ready for use. It has all the
basic functionality needed to test the application with Plack::Test and
the same time benefit from the old UnitTestContrib code.

No documentation yet but it come in a day or two.

- Added PlackPostTests as sample test suite for PlackTestCase.

- Extracted all code which can serve for both
FoswikiTestCase/FoswikiFnTestCase and PlackTestCase into a new role
FoswikiTestRole. This also includes splitting of test initialization code
into several `setupSomething()' methods.

- Renamed pushApp/popApp test case methods to saveState/restoreState to
correspond better with their purpose.

- Step-by-step replacement of Foswiki::Func::apiFunc() to
$Foswiki::app->apiFunc() or $this->app->apiFunc() wherever possible.

- Step-by-step switching from 'use Moo' to 'use Foswiki::Class'.

- Dropping support for old-style positional parameters for object
constructors.

- Added new exception Foswiki::Exception::FileOp for failed file
operations. It automates use of $!.

- Unit::TestApp now registers callbacks as early as possible – before
Foswiki::App::cfg attribute get initialized. This is to make it possible
for tests to manipulate with LSC before application is completely
initialized.

- Continue replacing $Foswiki::cfg with app->cfg->data.

- Added isGuest() method to Foswiki::Users.

- Added parameter `app' to Foswiki::Class. It automates applying of
Foswiki::AppObject role to a class.

- Fixed a strange bug where Foswiki::App::user attribute read was
overoptimized for reading when passed as a method argument. The
optimizations resulted in stack corruption if the attribute has been
changed before completing the method. So, it is now mandatory for the
attribute to be lazy and have a builder.

- `postConfig' callback is now raised by Foswiki::App constructor right
after checking the configuration attribute status and before any other
initialization is done.

- Fixed exception handling in Foswiki::UI::Register.

- Foswiki::Aux::Localize::setLocalizeFlags is now returning key/value pairs
list instead of hashref. This is to simplify it's use with inheritance.

- Fixed test case registerUser() method failing to detect errors generated
by Foswiki::UI::Register.
  • Loading branch information
vrurg committed Aug 26, 2016
1 parent 1c61fb9 commit 06435e6
Show file tree
Hide file tree
Showing 35 changed files with 1,782 additions and 927 deletions.
156 changes: 85 additions & 71 deletions TopicUserMappingContrib/lib/Foswiki/Users/TopicUserMapping.pm

Large diffs are not rendered by default.

763 changes: 763 additions & 0 deletions UnitTestContrib/lib/Unit/FoswikiTestRole.pm

Large diffs are not rendered by default.

339 changes: 281 additions & 58 deletions UnitTestContrib/lib/Unit/PlackTestCase.pm

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions UnitTestContrib/lib/Unit/TestApp.pm
Expand Up @@ -9,7 +9,6 @@ use Scalar::Util qw(blessed weaken refaddr);
use Try::Tiny;

use Foswiki::Class qw(callbacks);
use namespace::clean;
extends qw(Foswiki::App);

callback_names qw(testPreHandleRequest testPostHandleRequest);
Expand Down Expand Up @@ -114,6 +113,12 @@ sub registerCallbacks {
$this->_cbRegistered(1);
}

before _prepareConfig => sub {
my $this = shift;

$this->registerCallbacks;
};

around _prepareRequest => sub {
my $orig = shift;
my $this = shift;
Expand All @@ -132,8 +137,6 @@ around handleRequest => sub {
my $orig = shift;
my $this = shift;

$this->registerCallbacks;

my $rc;
try {
$this->callback('testPreHandleRequest');
Expand Down
8 changes: 3 additions & 5 deletions UnitTestContrib/lib/Unit/TestRunner.pm
Expand Up @@ -18,13 +18,11 @@ use Unit::Eavesdrop ();
use Devel::Symdump ();
use File::Spec ();

use Moo;
use namespace::clean;

extends 'Foswiki::Object';

use Assert;

use Foswiki::Class;
extends qw(Foswiki::Object);

sub CHECKLEAK { 0 || $ENV{FOSWIKI_CHECKLEAK} }

BEGIN {
Expand Down
2 changes: 0 additions & 2 deletions UnitTestContrib/test/unit/ConfigureTestCase.pm
Expand Up @@ -78,8 +78,6 @@ LSC
die "Can't open " . $this->lscpath . " for write: $!"
if -e $this->lscpath;
}

$| = 1;
};

around tear_down => sub {
Expand Down
2 changes: 1 addition & 1 deletion UnitTestContrib/test/unit/Fn_SEARCH.pm
Expand Up @@ -43,7 +43,7 @@ around BUILDARGS => sub {
# This test is run in a separate process to be able to reclaim that memory
# after the test is complete.
sub run_in_new_process {
return 1;
return 0;
}

our $AElig;
Expand Down
2 changes: 0 additions & 2 deletions UnitTestContrib/test/unit/FormattingTests.pm
Expand Up @@ -270,8 +270,6 @@ around tear_down => sub {
$this->removeWebFixture('This(is)')
if ( Foswiki::Func::webExists('This(is)') );
$orig->( $this, @_ );

$| = 0;
};

around loadExtraConfig => sub {
Expand Down
144 changes: 1 addition & 143 deletions UnitTestContrib/test/unit/FoswikiFnTestCase.pm
Expand Up @@ -31,31 +31,10 @@ use Foswiki::UI::Register();
use Try::Tiny;
use Carp qw(cluck);

our @mails;

use Moo;
use namespace::clean;
extends qw(FoswikiTestCase);

has test_web => (
is => 'rw',
lazy => 1,
clearer => 1,
builder => sub {
my $testSuite = $_[0]->testSuite;
return 'Temporary' . $testSuite . 'TestWeb' . $testSuite;
},
);
has test_topic => (
is => 'rw',
lazy => 1,
builder => sub { return 'TestTopic' . $_[0]->testSuite; },
);
has users_web => (
is => 'rw',
lazy => 1,
builder => sub { return 'Temporary' . $_[0]->testSuite . 'UsersWeb'; },
);
has test_user_forename => ( is => 'rw', );
has test_user_surname => ( is => 'rw', );
has test_user_wikiname => ( is => 'rw', );
Expand Down Expand Up @@ -91,24 +70,7 @@ around loadExtraConfig => sub {
$cfgData->{Store}{Implementation} = "Foswiki::Store::PlainFile";
$cfgData->{RCS}{AutoAttachPubFiles} = 0;

$cfgData->{Register}{AllowLoginName} = 1;
$cfgData->{Htpasswd}{FileName} = $cfgData->{WorkingDir} . "/htpasswd";
unless ( -e $cfgData->{Htpasswd}{FileName} ) {
my $fh;
open( $fh, ">:encoding(utf-8)", $cfgData->{Htpasswd}{FileName} )
|| die $!;
close($fh) || die $!;
}
$cfgData->{PasswordManager} = 'Foswiki::Users::HtPasswdUser';
$cfgData->{Htpasswd}{GlobalCache} = 0;
$cfgData->{UserMappingManager} = 'Foswiki::Users::TopicUserMapping';
$cfgData->{LoginManager} = 'Foswiki::LoginManager::TemplateLogin';
$cfgData->{Register}{EnableNewUserRegistration} = 1;
$cfgData->{RenderLoggedInButUnknownUsers} = 0;

$cfgData->{Register}{NeedVerification} = 0;
$cfgData->{MinPasswordLength} = 0;
$cfgData->{UsersWebName} = $this->users_web;
$this->setupUserRegistration;
};

around set_up => sub {
Expand All @@ -125,8 +87,6 @@ around set_up => sub {
},
);

@mails = ();
$this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail );
my $webObject = $this->populateNewWeb( $this->test_web );
undef $webObject;
$this->clear_test_topicObject;
Expand Down Expand Up @@ -165,8 +125,6 @@ around tear_down => sub {
$this->removeWebFixture( $cfg->data->{UsersWebName} );
unlink( $Foswiki::cfg{Htpasswd}{FileName} );

@mails = ();

$orig->( $this, @_ );
};

Expand All @@ -183,104 +141,4 @@ sub removeWeb {
$this->removeWebFixture($web);
}

=begin TML
---++ StaticMethod sentMail($net, $mess)
Default implementation for the callback used by Net.pm. Sent mails are
pushed onto a global variable @FoswikiFnTestCase::mails.
=cut

sub sentMail {
my ( $net, $mess ) = @_;
push( @mails, $mess );
return undef;
}

=begin TML
---++ ObjectMethod registerUser($loginname, $forename, $surname, $email)
Can be used by subclasses to register test users.
=cut

sub registerUser {
my ( $this, $loginname, $forename, $surname, $email ) = @_;

$this->pushApp;

my $reqParams = {
'TopicName' => ['UserRegistration'],
'Twk1Email' => [$email],
'Twk1WikiName' => ["$forename$surname"],
'Twk1Name' => ["$forename $surname"],
'Twk0Comment' => [''],
'Twk1FirstName' => [$forename],
'Twk1LastName' => [$surname],
'action' => ['register']
};

if ( $Foswiki::cfg{Register}{AllowLoginName} ) {
$reqParams->{"Twk1LoginName"} = $loginname;
}

$this->createNewFoswikiApp(
requestParams => { initializer => $reqParams, },
engineParams => {
initialAttributes =>
{ path_info => "/" . $this->users_web . "/UserRegistration", },
},
);
$this->assert(
$this->app->store->topicExists(
$this->test_web, $Foswiki::cfg{WebPrefsTopicName}
)
);

$this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail );
try {
my $uiRegister = $this->create('Foswiki::UI::Register');
$this->captureWithKey(
register_cgi => \&Foswiki::UI::Register::register_cgi,
$uiRegister,
);
}
catch {
my $e = $_;
if ( $e->isa('Foswiki::OopsException') ) {
if ( $this->check_dependency('Foswiki,<,1.2') ) {
$this->assert_str_equals( "attention", $e->{template},
$e->stringify() );
$this->assert_str_equals( "thanks", $e->{def},
$e->stringify() );
}
else {
$this->assert_str_equals( "register", $e->{template},
$e->stringify() );
$this->assert_str_equals( "thanks", $e->{def},
$e->stringify() );
}
}
elsif ( $e->isa('Foswiki::AccessControlException') ) {
$this->assert( 0, $e->stringify );
}
elsif ( $e->isa('Foswiki::Exception') ) {
$this->assert( 0, $e->stringify );
}
else {
$this->assert( 0, "expected an oops redirect" );
}
};

# Reload caches
#$this->createNewFoswikiApp( requestParams => $q );
#$this->app->net->setMailHandler( \&FoswikiFnTestCase::sentMail );
$this->popApp;

# Reset
$this->app->users->mapping->invalidate;
}

1;

0 comments on commit 06435e6

Please sign in to comment.