File Coverage

blib/lib/Email/Stuffer/TestLinks.pm
Criterion Covered Total %
statement 21 21 100.0
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 28 28 100.0


line stmt bran cond sub pod time code
1             package Email::Stuffer::TestLinks;
2              
3 1     1   298142 use strict;
  1         11  
  1         42  
4 1     1   6 use warnings;
  1         3  
  1         51  
5              
6             our $VERSION = 0.020;
7              
8 1     1   7 use Test::Most;
  1         3  
  1         10  
9 1     1   2048 use Mojolicious 6.00;
  1         341185  
  1         7  
10 1     1   64 use Mojo::UserAgent;
  1         2  
  1         6  
11 1     1   37 use Email::Stuffer;
  1         2  
  1         21  
12 1     1   4 use Class::Method::Modifiers qw/ install_modifier /;
  1         2  
  1         447  
13              
14             =head1 SYNOPSIS
15              
16             use Email::Stuffer::TestLinks;
17              
18             =head1 NAME
19              
20             Email::Stuffer::TestLinks - validates links in HTML emails sent by
21             Email::Stuffer>send_or_die()
22              
23             =head1 DESCRIPTION
24              
25             When this module is included in a test, it parses HTML links (
26             in every email sent through Email::Stuffer->send_or_die(). Each URI must get a
27             successful response code (200 range) and the returned pagetitle must not contain
28             'error' or 'not found'.
29              
30             =cut
31              
32             install_modifier 'Email::Stuffer', after => send_or_die => sub {
33              
34             my $self = shift;
35             my $ua = Mojo::UserAgent->new(max_redirects => 10, connect_timeout => 5);
36              
37             my %urls;
38             $self->email->walk_parts(
39             sub {
40             my ($part) = @_;
41             return unless ($part->content_type && $part->content_type =~ /text\/html/i);
42             my $dom = Mojo::DOM->new($part->body);
43             my $links = $dom->find('a')->map(attr => 'href')->compact;
44              
45             # Exclude anchors, mailto
46             $urls{$_} = 1 for (grep { !/^mailto:/ } @$links);
47             });
48              
49             for my $url (sort keys %urls) {
50              
51             my $err = '';
52              
53             if ($url =~ /^[#\/]/) {
54             $err = "$url is not a valid URL for an email";
55             } else {
56             my $tx = $ua->get($url);
57              
58             if ($tx->success) {
59             my $res = $tx->result;
60              
61             if ($res->code !~ /^2\d\d/) {
62             $err = "HTTP code was " . $res->code;
63             } else {
64             my $title = $res->dom->at('title')->text;
65             $err = "Page title contains text '$1'"
66             if $title =~ /(error|not found)/i;
67             }
68             } else {
69             $err = "Could not retrieve URL: " . $tx->error->{message};
70             }
71             }
72             ok(!$err, "Link in email works ($url)") or diag($err);
73             }
74              
75             };
76              
77             1;