added WaitForUserConfirmation activity
This commit is contained in:
parent
4aeb70d323
commit
182fc16021
9 changed files with 526 additions and 3 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
7.10.21
|
7.10.21
|
||||||
- added #9668 extension template variable to attachment loops for the following assets:
|
- added #9668 extension template variable to attachment loops for the following assets:
|
||||||
Article,Post,Event,File,Form::Attachments,Folder
|
Article,Post,Event,File,Form::Attachments,Folder
|
||||||
|
- added WaitForUserConfirmation workflow activity
|
||||||
- added the optional WebGUI::Content::PDFGenerator, not enabled by default
|
- added the optional WebGUI::Content::PDFGenerator, not enabled by default
|
||||||
(see the module's documentation).
|
(see the module's documentation).
|
||||||
- fixed #12204: Default forum notification template produces invalid HTML
|
- fixed #12204: Default forum notification template produces invalid HTML
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,23 @@ my $quiet; # this line required
|
||||||
|
|
||||||
|
|
||||||
my $session = start(); # this line required
|
my $session = start(); # this line required
|
||||||
|
addWaitForConfirmationWorkflow($session);
|
||||||
# upgrade functions go here
|
|
||||||
|
|
||||||
finish($session); # this line required
|
finish($session); # this line required
|
||||||
|
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------
|
||||||
|
sub addWaitForConfirmationWorkflow {
|
||||||
|
my $session = shift;
|
||||||
|
my $c = $session->config;
|
||||||
|
my $exists = $c->get('workflowActivities/WebGUI::User');
|
||||||
|
my $class = 'WebGUI::Workflow::Activity::WaitForUserConfirmation';
|
||||||
|
unless (grep { $_ eq $class } @$exists) {
|
||||||
|
print "Adding WaitForUserConfirmation workflow..." unless $quiet;
|
||||||
|
$c->addToArray('workflowActivities/WebGUI::User' => $class);
|
||||||
|
print "Done!\n" unless $quiet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#----------------------------------------------------------------------------
|
#----------------------------------------------------------------------------
|
||||||
# Describe what our function does
|
# Describe what our function does
|
||||||
#sub exampleFunction {
|
#sub exampleFunction {
|
||||||
|
|
|
||||||
|
|
@ -201,6 +201,7 @@ sub getOperations {
|
||||||
'ajaxDeleteUser' => 'User',
|
'ajaxDeleteUser' => 'User',
|
||||||
'ajaxUpdateUser' => 'User',
|
'ajaxUpdateUser' => 'User',
|
||||||
'becomeUser' => 'User',
|
'becomeUser' => 'User',
|
||||||
|
'confirmUserEmail' => 'User',
|
||||||
'deleteUser' => 'User',
|
'deleteUser' => 'User',
|
||||||
'editUser' => 'User',
|
'editUser' => 'User',
|
||||||
'editUserSave' => 'User',
|
'editUserSave' => 'User',
|
||||||
|
|
|
||||||
|
|
@ -418,6 +418,38 @@ sub www_ajaxCreateUser {
|
||||||
|
|
||||||
#-------------------------------------------------------------------
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 www_confirmUserEmail ( )
|
||||||
|
|
||||||
|
Process links clicked from mails sent out by the WaitForUserConfmration
|
||||||
|
workflow activity.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub www_confirmUserEmail {
|
||||||
|
my $session = shift;
|
||||||
|
my $f = $session->form;
|
||||||
|
my $instanceId = $f->get('instanceId');
|
||||||
|
my $token = $f->get('token');
|
||||||
|
my $actId = $f->get('activityId');
|
||||||
|
my $activity = WebGUI::Workflow::Activity->new($session, $actId)
|
||||||
|
or die;
|
||||||
|
my $instance = WebGUI::Workflow::Instance->new($session, $instanceId)
|
||||||
|
or die;
|
||||||
|
if ($activity->confirm($instance, $token)) {
|
||||||
|
my $msg = $activity->get('okMessage');
|
||||||
|
unless ($msg) {
|
||||||
|
my $i18n = WebGUI::International->new($session, 'WebGUI');
|
||||||
|
$msg = $i18n->get('ok');
|
||||||
|
}
|
||||||
|
return $session->style->userStyle($msg);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return $session->privilege->noAccess;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
=head2 www_ajaxDeleteUser ( )
|
=head2 www_ajaxDeleteUser ( )
|
||||||
|
|
||||||
Delete a user using a web service.
|
Delete a user using a web service.
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,29 @@ These methods are available from this class:
|
||||||
|
|
||||||
#-------------------------------------------------------------------
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 changeWorkflow ( $workflowId, $instance, $skipDelete )
|
||||||
|
|
||||||
|
Kicks a new workflow in a new instance with the same object the current
|
||||||
|
instance has, deleting the old instance unless you say otherwise.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub changeWorkflow {
|
||||||
|
my ($self, $workflowId, $instance, $skipDelete) = @_;
|
||||||
|
WebGUI::Workflow::Instance->create(
|
||||||
|
$self->session, {
|
||||||
|
workflowId => $workflowId,
|
||||||
|
methodName => $instance->get('methodName'),
|
||||||
|
className => $instance->get('className'),
|
||||||
|
parameters => $instance->get('parameters'),
|
||||||
|
priority => $instance->get('priority'),
|
||||||
|
}
|
||||||
|
)->start(1);
|
||||||
|
$instance->delete() unless $skipDelete;
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
=head2 cleanup ( )
|
=head2 cleanup ( )
|
||||||
|
|
||||||
Override this activity to add a cleanup routine to be run if an instance
|
Override this activity to add a cleanup routine to be run if an instance
|
||||||
|
|
|
||||||
270
lib/WebGUI/Workflow/Activity/WaitForUserConfirmation.pm
Normal file
270
lib/WebGUI/Workflow/Activity/WaitForUserConfirmation.pm
Normal file
|
|
@ -0,0 +1,270 @@
|
||||||
|
package WebGUI::Workflow::Activity::WaitForUserConfirmation;
|
||||||
|
|
||||||
|
use warnings;
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use base 'WebGUI::Workflow::Activity';
|
||||||
|
use WebGUI::Asset::Template;
|
||||||
|
use WebGUI::International;
|
||||||
|
use WebGUI::Inbox::Message;
|
||||||
|
use WebGUI::Macro;
|
||||||
|
use Kwargs;
|
||||||
|
use Tie::IxHash;
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 confirm ( $instance, $token )
|
||||||
|
|
||||||
|
Returns true (and sets the workflow as done) if the token matches the one we
|
||||||
|
generated for the email.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub confirm {
|
||||||
|
my ($self, $instance, $token) = @_;
|
||||||
|
my $id = $self->getId;
|
||||||
|
return 0 unless $token eq $instance->getScratch("$id-token");
|
||||||
|
$instance->setScratch("$id-status", 'done');
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 definition ( )
|
||||||
|
|
||||||
|
See WebGUI::Workflow::Activity::definition for details.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub definition {
|
||||||
|
my ($class, $session, $def) = @_;
|
||||||
|
my $i18n = WebGUI::International->new(
|
||||||
|
$session, 'Activity_WaitForUserConfirmation'
|
||||||
|
);
|
||||||
|
|
||||||
|
tie my %props, 'Tie::IxHash', (
|
||||||
|
emailFrom => {
|
||||||
|
fieldType => 'user',
|
||||||
|
defaultValue => 3,
|
||||||
|
},
|
||||||
|
emailSubject => {
|
||||||
|
fieldType => 'text',
|
||||||
|
defaultValue => 'Confirmation Email',
|
||||||
|
},
|
||||||
|
template => {
|
||||||
|
fieldType => 'textarea',
|
||||||
|
defaultValue => $i18n->get('your template goes here'),
|
||||||
|
},
|
||||||
|
templateParser => {
|
||||||
|
fieldType => 'templateParser',
|
||||||
|
defaultValue => $session->config->get('defaultTemplateParser'),
|
||||||
|
},
|
||||||
|
okMessage => {
|
||||||
|
fieldType => 'HTMLArea',
|
||||||
|
},
|
||||||
|
waitBetween => {
|
||||||
|
fieldType => 'interval',
|
||||||
|
defaultValue => 60*5
|
||||||
|
},
|
||||||
|
expireAfter => {
|
||||||
|
fieldType => 'interval',
|
||||||
|
defaultValue => 60*60*24*7,
|
||||||
|
},
|
||||||
|
doOnExpire => {
|
||||||
|
fieldType => 'workflow',
|
||||||
|
type => 'WebGUI::User',
|
||||||
|
none => 1,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
for my $key (keys %props) {
|
||||||
|
$props{$key}{label} = $i18n->get("$key label");
|
||||||
|
$props{$key}{hoverHelp} = $i18n->get("$key hoverHelp");
|
||||||
|
}
|
||||||
|
|
||||||
|
push @$def, {
|
||||||
|
name => $i18n->get('topicName'),
|
||||||
|
properties => \%props,
|
||||||
|
};
|
||||||
|
|
||||||
|
return $class->SUPER::definition( $session, $def );
|
||||||
|
}
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 execute ( )
|
||||||
|
|
||||||
|
See WebGUI::Workflow::Activity::execute for details.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub execute {
|
||||||
|
my ($self, $object, $instance) = @_;
|
||||||
|
my $id = $self->getId;
|
||||||
|
my $statk = "$id-status";
|
||||||
|
my $start = "$id-started";
|
||||||
|
my $status = $instance->getScratch($statk);
|
||||||
|
my $subject = $self->get('emailSubject');
|
||||||
|
my $parser = $self->get('templateParser');
|
||||||
|
WebGUI::Macro::process(\$subject);
|
||||||
|
my $body = WebGUI::Asset::Template->processRaw(
|
||||||
|
$self->session,
|
||||||
|
$self->get('template'),
|
||||||
|
$self->getTemplateVariables($object, $instance),
|
||||||
|
$parser,
|
||||||
|
);
|
||||||
|
WebGUI::Macro::process(\$body);
|
||||||
|
unless ($status) {
|
||||||
|
$instance->setScratch($start => $self->now);
|
||||||
|
$self->sendEmail(
|
||||||
|
from => $self->get('emailFrom'),
|
||||||
|
to => $object->userId,
|
||||||
|
subject => $subject,
|
||||||
|
body => $body,
|
||||||
|
);
|
||||||
|
$instance->setScratch($statk => 'waiting');
|
||||||
|
return $self->wait;
|
||||||
|
}
|
||||||
|
return $self->COMPLETE if $status eq 'done' || $status eq 'expired';
|
||||||
|
if ($status eq 'waiting') {
|
||||||
|
my $end = $instance->getScratch($start) + $self->get('expireAfter');
|
||||||
|
if ($self->now > $end) {
|
||||||
|
$self->expire($instance);
|
||||||
|
$instance->setScratch($statk => 'expired');
|
||||||
|
return $self->COMPLETE;
|
||||||
|
}
|
||||||
|
return $self->wait;
|
||||||
|
}
|
||||||
|
$self->session->log->error("Unknown status: $status");
|
||||||
|
return $self->ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 expire ( $instance )
|
||||||
|
|
||||||
|
Deletes the workflow instance and kicks off a configured workflow if there is
|
||||||
|
one.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub expire {
|
||||||
|
my ($self, $instance) = @_;
|
||||||
|
if (my $id = $self->get('doOnExpire')) {
|
||||||
|
$self->changeWorkflow($id, $instance);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$instance->delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 getTemplateVariables ( $object, $instance )
|
||||||
|
|
||||||
|
Returns the variables to be used in rendering the email template.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub getTemplateVariables {
|
||||||
|
my ($self, $object, $instance) = @_;
|
||||||
|
|
||||||
|
my $user = $object->get;
|
||||||
|
|
||||||
|
# Kill all humans. I means references. Currently there seems to be a bug
|
||||||
|
# in _rewriteVars in some of the template plugins that disallows us from
|
||||||
|
# using arrayrefs with just strings in them, which is a common occurrence
|
||||||
|
# in profile fields. When that bug gets fixed, we can (and should) take
|
||||||
|
# this out.
|
||||||
|
delete @{$user}{grep {ref $user->{$_} } keys %$user};
|
||||||
|
|
||||||
|
return {
|
||||||
|
user => $user,
|
||||||
|
link => $self->link($instance),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 link ( $instance )
|
||||||
|
|
||||||
|
Returns the URL that needs to be visited by the user.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub link {
|
||||||
|
my ($self, $instance) = @_;
|
||||||
|
my $url = $self->session->url;
|
||||||
|
my $aid = $self->getId;
|
||||||
|
my $iid = $instance->getId;
|
||||||
|
my $token = $instance->getScratch("$aid-token");
|
||||||
|
$instance->setScratch("$aid-token", $token = $self->token) unless $token;
|
||||||
|
my $path = $url->page(
|
||||||
|
"op=confirmUserEmail;instanceId=$iid;token=$token;activityId=$aid"
|
||||||
|
);
|
||||||
|
return $url->getSiteURL . $url->gateway($path);
|
||||||
|
}
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 now ( )
|
||||||
|
|
||||||
|
Just returns the current time, nice for testing.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub now { time }
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 sendEmail ( { from, to, subject, body } )
|
||||||
|
|
||||||
|
Takes a user to send email from, to, with a subject and a body all as
|
||||||
|
keywords. Mostly here for testing, it just calls
|
||||||
|
WebGUI::Inbox::Message->create() with proper arguments. 'from' and 'to' are
|
||||||
|
userIds, not user objects.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub sendEmail {
|
||||||
|
my ($self, $from, $to, $subject, $body) = kwn @_, 1,
|
||||||
|
qw(from to subject body);
|
||||||
|
|
||||||
|
WebGUI::Inbox::Message->create(
|
||||||
|
$self->session, {
|
||||||
|
message => $body,
|
||||||
|
subject => $subject,
|
||||||
|
status => 'pending',
|
||||||
|
userId => $to,
|
||||||
|
sentBy => $from,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 token ( )
|
||||||
|
|
||||||
|
Returns a random string to use as a token in the confirmation link
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub token {
|
||||||
|
my $self = shift;
|
||||||
|
$self->session->id->generate;
|
||||||
|
}
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 wait ( )
|
||||||
|
|
||||||
|
Waits for the configured waitBetween interval.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub wait {
|
||||||
|
my $self = shift;
|
||||||
|
return $self->WAITING($self->get('waitBetween'));
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
||||||
74
lib/WebGUI/i18n/English/Activity_WaitForUserConfirmation.pm
Normal file
74
lib/WebGUI/i18n/English/Activity_WaitForUserConfirmation.pm
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
package WebGUI::i18n::English::Activity_WaitForUserConfirmation;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
our $I18N = {
|
||||||
|
'doOnExpire hoverHelp' => {
|
||||||
|
message => q{Workflow to run after the waiting period has expired.},
|
||||||
|
lastUpdated => 1311365415,
|
||||||
|
},
|
||||||
|
'doOnExpire label' => {
|
||||||
|
message => q{Do On Expire},
|
||||||
|
lastUpdated => 1311365395,
|
||||||
|
},
|
||||||
|
'emailFrom hoverHelp' => {
|
||||||
|
message => q{Which user should the confirmation email be from?},
|
||||||
|
lastUpdated => 1311363981,
|
||||||
|
},
|
||||||
|
'emailFrom label' => {
|
||||||
|
message => q{Email From},
|
||||||
|
lastUpdated => 1311363958,
|
||||||
|
},
|
||||||
|
'emailSubject label' => {
|
||||||
|
message => q{Email Subject},
|
||||||
|
lastUpdated => 1311363994,
|
||||||
|
},
|
||||||
|
'expireAfter hoverHelp' => {
|
||||||
|
message => q{How long should we wait for the user to respond?},
|
||||||
|
lastUpdated => 1311363900,
|
||||||
|
},
|
||||||
|
'expireAfter label' => {
|
||||||
|
message => q{Expire After},
|
||||||
|
lastUpdated => 1311363885,
|
||||||
|
},
|
||||||
|
'okMessage label' => {
|
||||||
|
message => q{Confirmation Message},
|
||||||
|
lastUpdated => 1311612584,
|
||||||
|
},
|
||||||
|
'okMessage hoverHelp' => {
|
||||||
|
message => q{Message to display to the user when he clicks the confirm link},
|
||||||
|
lastUpdated => 1311612632,
|
||||||
|
},
|
||||||
|
'template hoverHelp' => {
|
||||||
|
message => q{Raw template code for the body of the email goes here.},
|
||||||
|
lastUpdated => 1311364201,
|
||||||
|
},
|
||||||
|
'template label' => {
|
||||||
|
message => q{Template},
|
||||||
|
lastUpdated => 1311364181,
|
||||||
|
},
|
||||||
|
'templateParser label' => {
|
||||||
|
message => q{Template Parser},
|
||||||
|
lastUpdated => 1311364015,
|
||||||
|
},
|
||||||
|
'topicName' => {
|
||||||
|
message => q{Wait For User Confirmation},
|
||||||
|
lastUpdated => 1311364913,
|
||||||
|
},
|
||||||
|
'waitBetween hoverHelp' => {
|
||||||
|
message => q{How long should we wait in between checks to see if the user has clicked the link?},
|
||||||
|
lastUpdated => 1311363934,
|
||||||
|
},
|
||||||
|
'waitBetween label' => {
|
||||||
|
message => q{Wait Interval},
|
||||||
|
lastUpdated => 1311363920,
|
||||||
|
},
|
||||||
|
'your template goes here' => {
|
||||||
|
message => q{Your template goes here!},
|
||||||
|
lastUpdated => 1311365274,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
1;
|
||||||
|
|
||||||
|
#vim:ft=perl
|
||||||
|
|
@ -155,6 +155,7 @@ checkModule('IO::Socket::SSL', );
|
||||||
checkModule('Net::Twitter', "3.13006" );
|
checkModule('Net::Twitter', "3.13006" );
|
||||||
checkModule('PerlIO::eol', "0.14" );
|
checkModule('PerlIO::eol', "0.14" );
|
||||||
checkModule('Monkey::Patch', '0.03' );
|
checkModule('Monkey::Patch', '0.03' );
|
||||||
|
checkModule('Kwargs', );
|
||||||
checkModule('Data::ICal', '0.16' );
|
checkModule('Data::ICal', '0.16' );
|
||||||
checkModule('common::sense', '3.2' );
|
checkModule('common::sense', '3.2' );
|
||||||
checkModule('Geo::Coder::Googlev3', '0.07' );
|
checkModule('Geo::Coder::Googlev3', '0.07' );
|
||||||
|
|
|
||||||
110
t/Workflow/Activity/WaitForUserConfirmation.t
Normal file
110
t/Workflow/Activity/WaitForUserConfirmation.t
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
use warnings;
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use FindBin;
|
||||||
|
use lib "$FindBin::Bin/../../lib";
|
||||||
|
use lib "$FindBin::Bin/../../t/lib";
|
||||||
|
|
||||||
|
use WebGUI::Test;
|
||||||
|
use Test::More tests => 28;
|
||||||
|
use Test::MockObject;
|
||||||
|
use Test::MockObject::Extends;
|
||||||
|
use WebGUI::Workflow::Activity;
|
||||||
|
use Kwargs;
|
||||||
|
use URI;
|
||||||
|
|
||||||
|
my $session = WebGUI::Test->session;
|
||||||
|
|
||||||
|
my $act = WebGUI::Workflow::Activity->newByPropertyHashRef(
|
||||||
|
$session, {
|
||||||
|
className => 'WebGUI::Workflow::Activity::WaitForUserConfirmation',
|
||||||
|
activityId => 'test-activity',
|
||||||
|
expireAfter => 60*60*24,
|
||||||
|
waitBetween => 60*5,
|
||||||
|
emailFrom => 3,
|
||||||
|
emailSubject => 'Confirmation Email',
|
||||||
|
templateParser => 'WebGUI::Asset::Template::TemplateToolkit',
|
||||||
|
template => 'Hey [% user.firstName %] [% user.lastName %], '
|
||||||
|
. 'click $link!',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
is $act->wait, $act->WAITING(60*5), 'wait helper method';
|
||||||
|
|
||||||
|
$act = Test::MockObject::Extends->new($act);
|
||||||
|
|
||||||
|
my (%scratch, %profile);
|
||||||
|
%profile = (
|
||||||
|
email => 'target@test.com',
|
||||||
|
firstName => 'Target',
|
||||||
|
lastName => 'Targetson',
|
||||||
|
);
|
||||||
|
|
||||||
|
my $user = Test::MockObject->new
|
||||||
|
->mock(get => sub { \%profile })
|
||||||
|
->mock(userId => sub { 'test-user-id' });
|
||||||
|
|
||||||
|
my $workflow = Test::MockObject->new
|
||||||
|
->mock(setScratch => sub { $scratch{$_[1]} = $_[2] })
|
||||||
|
->mock(getScratch => sub { $scratch{$_[1]} })
|
||||||
|
->mock(getId => sub { 'test-workflow' });
|
||||||
|
|
||||||
|
my ($expired, $sent) = (0,0);
|
||||||
|
$act->mock(sendEmail => sub { $sent++ })
|
||||||
|
->mock(expire => sub { $expired++ })
|
||||||
|
->mock(now => sub { 100 })
|
||||||
|
->mock(token => sub { 'test-token' });
|
||||||
|
|
||||||
|
my $st = 'test-activity-status';
|
||||||
|
|
||||||
|
sub ex { $act->execute($user, $workflow) }
|
||||||
|
sub clr {
|
||||||
|
delete @scratch{'test-activity-started', $st};
|
||||||
|
$sent = 0;
|
||||||
|
$expired = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
is ex, $act->wait, 'from scratch returns waiting';
|
||||||
|
is $sent, 1, 'one email sent';
|
||||||
|
is $scratch{$st}, 'waiting', 'scratch is waiting';
|
||||||
|
is $scratch{'test-activity-started'}, 100, 'started at mocked time';
|
||||||
|
is ex, $act->wait, 'still waiting';
|
||||||
|
is $sent, 1, 'did not send second email';
|
||||||
|
is $scratch{$st}, 'waiting', 'scratch still waiting';
|
||||||
|
$scratch{$st} = 'done';
|
||||||
|
is ex, $act->COMPLETE, 'returns complete after done';
|
||||||
|
is ex, $act->COMPLETE, 'forever';
|
||||||
|
is $expired, 0, 'not expired though';
|
||||||
|
clr;
|
||||||
|
is $act->execute($user, $workflow), $act->wait, 'waiting after clear';
|
||||||
|
is $sent, 1, 'one email sent';
|
||||||
|
$act->mock(now => sub { 60*60*24+101 });
|
||||||
|
is ex, $act->COMPLETE, 'complete after expired';
|
||||||
|
is $scratch{$st}, 'expired', 'expired status';
|
||||||
|
is $expired, 1, 'expire called';
|
||||||
|
|
||||||
|
clr;
|
||||||
|
my ($self, $to, $from, $subject, $body);
|
||||||
|
$act->mock(
|
||||||
|
sendEmail => sub {
|
||||||
|
($self, $to, $from, $subject, $body) = kwn @_, 1,
|
||||||
|
qw(to from subject body);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
ex;
|
||||||
|
is $to, $user->userId, 'to';
|
||||||
|
is $from, 3, 'from';
|
||||||
|
is $subject, 'Confirmation Email', 'subject';
|
||||||
|
my $link = URI->new($act->link($workflow));
|
||||||
|
my %p = $link->query_form;
|
||||||
|
is $body, "Hey Target Targetson, click $link!", 'body';
|
||||||
|
is $p{token}, 'test-token', 'token in link';
|
||||||
|
is $p{instanceId}, 'test-workflow', 'instance id in link';
|
||||||
|
is $p{activityId}, 'test-activity', 'activity id in link';
|
||||||
|
$act->unmock('token');
|
||||||
|
is $act->link($workflow), $link, 'token only generated once';
|
||||||
|
|
||||||
|
ok !$act->confirm($workflow, 'not-the-token'), 'bad token';
|
||||||
|
is $scratch{$st}, 'waiting', 'wait after bad';
|
||||||
|
ok $act->confirm($workflow, 'test-token'), 'good token';
|
||||||
|
is $scratch{$st}, 'done', 'done after good';
|
||||||
Loading…
Add table
Add a link
Reference in a new issue