Recently I've been setting up an extensive test harness suite for a web-based application running on the Catalyst Web Framework for Perl.
In addition to the popular Test::More
CPAN module, many of the tests make use of the CPAN module Test::WWW::Mechanize::Catalyst
where I run automated scripts to access various pages, fill in fields with various values, submit forms and check for success or failure.
One of the tests involves creating a new user account that generates a notification email which is sent to the new user. Within the message text there is a verification link. The idea is that upon receiving this email, the user will click on this link and be redirected back to the application to a welcome page. This welcome page verifies that registration has been completed successfully. The user is invited to login in by submitting a form with the username and password pre-filled.
The problem is that I do not want to be generating all kinds of external emails into the big bad world for these tests. Besides, how can I use automated scripts when they depend on external events like users having to click on links in emails wherever they might be?
So here's the trick. First of all I redefine the Email::Send::send()
method so that I can hook into it thereby mocking it's behavior. This redefined method is used to scrape out the embedded validation link we must click on in order to finish the registration process.
our $email_mime_ref;
{
no warnings qw/once redefine/;
*Email::Send::send = sub {
my ($self, $message, @args) = @_;
$main::email_mime_ref = $message; return 1; };
}
Note that we use no warnings qw/once redefine/
in order to disable the warning messages for redefining the method and only using it once.
Whenever Email::Send::send()
is called, we copy the message for later use. Note that since we are in the namespace of Email::Send
when this is called, we need to make sure that the message is copied back into the namespace of where we are calling from, namely $main::*
:
$main::email_mime_ref = $message;
Later on in the test suite it is time to submit the form like this:
$mech->submit_form(
form_number => 0,
fields => $fields,
button => 'submit' );
Now scan through the message text and extract the uri, there should only be one present. I'm using the CPAN module URI::Find
to simplify life.
my @uris;
my $finder = URI::Find->new( sub { push @uris, shift; } );
$finder->find(\$email_mime_ref->body_raw);
As a sanity check (you never know) I check that indeed only one link is present in the message text:
is(@uris, 1, "Found only one URI '$uris[0]' in email message");
Finally, we simulate clicking on this link which should bring us back to the welcome page:
$mech->get_ok($uris[0], "Click on URI '$uris[0]'");
$mech->content_contains("Welcome " . lc($username) .
", your email has been validated. Please log in.");
We did it, so let's pat ourselves on the shoulders and call it a night.
Recent Comments
- Charles
- jpmcfarlane
- Kiffin
- jpmcfarlane
- KathleenC