File Coverage

blib/lib/Test/HTTPStatus.pm
Criterion Covered Total %
statement 52 81 64.2
branch 0 20 0.0
condition 0 14 0.0
subroutine 14 18 77.7
pod 2 2 100.0
total 68 135 50.3


line stmt bran cond sub pod time code
1             package Test::HTTPStatus;
2              
3 1     1   366785 use strict;
  1         3  
  1         65  
4 1     1   6 use warnings;
  1         2  
  1         83  
5              
6             =encoding utf-8
7              
8             =head1 NAME
9              
10             Test::HTTPStatus - check an HTTP status
11              
12             =head1 SYNOPSIS
13              
14             use Test::HTTPStatus tests => 2;
15              
16             http_ok('https://www.perl.org', HTTP_OK);
17              
18             http_ok($url, $status);
19              
20             =head1 DESCRIPTION
21              
22             Check the HTTP status for a resource.
23              
24             =cut
25              
26 1     1   14 use v5.10.1; # Mojolicious is v5.10.1 and later
  1         4  
27             our $VERSION = '2.12';
28              
29 1     1   6 use parent 'Test::Builder::Module';
  1         13  
  1         10  
30              
31 1     1   88 use Carp qw(carp);
  1         1  
  1         106  
32             # use HTTP::SimpleLinkChecker;
33 1     1   892 use Mojo::UserAgent;
  1         652559  
  1         11  
34 1     1   78 use Test::Builder::Module;
  1         4  
  1         15  
35 1     1   70 use Mojo::URL;
  1         6  
  1         6  
36              
37             my $Test = __PACKAGE__->builder;
38              
39 1     1   57 use constant NO_URL => -1;
  1         2  
  1         119  
40 1     1   8 use constant INVALID_URL => -2;
  1         13  
  1         60  
41 1     1   6 use constant HTTP_OK => 200;
  1         1  
  1         69  
42 1     1   7 use constant HTTP_NOT_FOUND => 404;
  1         1  
  1         96  
43              
44             sub import {
45 1     1   12 my $self = shift;
46 1         2 my $caller = caller;
47 1     1   7 no strict 'refs';
  1         2  
  1         940  
48 1         4 *{$caller.'::http_ok'} = \&http_ok;
  1         11  
49 1         3 *{$caller.'::NO_URL'} = \&NO_URL;
  1         4  
50 1         3 *{$caller.'::INVALID_URL'} = \&INVALID_URL;
  1         5  
51 1         2 *{$caller.'::HTTP_OK'} = \&HTTP_OK;
  1         4  
52 1         2 *{$caller.'::HTTP_NOT_FOUND'} = \&HTTP_NOT_FOUND;
  1         4  
53              
54 1         7 $Test->exported_to($caller);
55 1         14 $Test->plan(@_);
56             }
57              
58             =head1 FUNCTIONS
59              
60             =head2 http_ok( URL [, HTTP_STATUS ] )
61              
62             http_ok( $url, $expected_status );
63              
64             Tests the HTTP status of the specified URL and reports whether it matches the expected status.
65              
66             =head3 Parameters
67              
68             =over 4
69              
70             =item * C (Required)
71              
72             The URL to be tested.
73             This must be a valid URL string.
74             If the URL is invalid or undefined, the test will fail, and an appropriate diagnostic message will be displayed.
75              
76             =item * C (Optional)
77              
78             The expected HTTP status code.
79             Defaults to C (200) if not provided.
80             This parameter should be one of the HTTP status constants exported by the module (e.g., C, C).
81              
82             =back
83              
84             =head3 Diagnostics
85              
86             On success, the test will pass with a message in the following format:
87              
88             Expected [], got [] for []
89              
90             On failure, the test will fail with one of the following messages:
91              
92             =over 4
93              
94             =item * C<[$url] does not appear to be anything>
95              
96             Indicates that the URL was undefined or missing.
97              
98             =item * C<[$url] does not appear to be a valid URL>
99              
100             Indicates that the URL string provided was invalid or malformed.
101              
102             =item * C
103              
104             Indicates that the request failed for an unexpected reason or returned a status not matching the expected value.
105              
106             =back
107              
108             =head3 Examples
109              
110             =over 4
111              
112             =item * Basic test with default expected status:
113              
114             http_ok('https://www.perl.org');
115              
116             This checks that the URL C returns an HTTP status of C (200).
117              
118             =item * Test with a custom expected status:
119              
120             http_ok('https://www.example.com/404', HTTP_NOT_FOUND);
121              
122             This checks that the URL C returns an HTTP status of C (404).
123              
124             =back
125              
126             =head3 Return Value
127              
128             The routine does not return any value.
129             Instead, it reports success or failure using the underlying test builder's C method.
130              
131             =cut
132              
133             sub http_ok {
134 0     0 1   my $url = shift;
135 0   0       my $expected = shift || HTTP_OK;
136              
137             # Always succeed when NO_NETWORK_TESTING is set
138 0 0         my $hash = $ENV{'NO_NETWORK_TESTING'} ? { status => $expected, url => $url } : _get_status( $url );
139              
140 0           my $status = $hash->{status};
141              
142 0 0 0       if(!defined($status)) {
    0          
    0          
    0          
143 0           $Test->ok(0, "[$url] status is not set");
144             } elsif(defined($expected) && ($expected == $status)) {
145 0           $Test->ok(1, "Expected [$expected], got [$status] for [$url]");
146             } elsif($status == NO_URL) {
147 0           $Test->ok( 0, "[$url] does not appear to be anything" );
148             } elsif( $status == INVALID_URL ) {
149 0           $Test->ok( 0, "[$url] does not appear to be a valid URL" );
150             } else {
151 0           $Test->ok(0, "Unknown failure for [$url] with status [$status]");
152             }
153             }
154              
155             sub _get_status {
156 0     0     my $string = shift;
157              
158 0 0         return { status => NO_URL } unless defined $string;
159              
160 0           my $url = Mojo::URL->new( $string );
161 0 0         return { status => INVALID_URL } unless $url->host();
162              
163 0           my $status = _check_link( $url );
164              
165 0           return { url => $url, status => $status };
166             }
167              
168             =head2 _check_link
169              
170             Verify the accessibility of a given URL by checking its HTTP status code using L.
171             It first attempts to send a HEAD request to the provided link,
172             which is useful for quickly checking if the resource exists without downloading its content.
173             If the response indicates no error (i.e., status code is below 400),
174             the function proceeds with a GET request to ensure a proper response is received.
175             The function then validates whether a valid HTTP response was obtained and returns the corresponding status code.
176             If the link is undefined or if no valid response is received, the function returns C.
177              
178             It is taken from the old module HTTP::SimpleLinkChecker.
179              
180             =cut
181              
182             our $UA ||= Mojo::UserAgent->new();
183             $UA->proxy->detect();
184             $UA->max_redirects(3);
185              
186             sub _check_link {
187 0     0     my $link = shift;
188              
189 0           say STDERR "Link is $link";
190 0 0         unless( defined $link ) {
191             # $ERROR = 'Received no argument';
192 0           return;
193             }
194              
195 0           my $transaction = $UA->head($link);
196 0           my $response = $transaction->res();
197              
198 0 0 0       if(!$response || !defined($response->code()) || (($response->code() >= 400) && ($response->code() != 404))) {
      0        
      0        
199 0           $transaction = $UA->get($link);
200 0           $response = $transaction->res();
201             }
202              
203 0 0         unless(ref($response)) {
204             # $ERROR = 'Could not get response';
205 0           return;
206             }
207              
208 0           return $response->code();
209             }
210              
211             =head2 user_agent
212              
213             Returns the user agent being used
214              
215             =cut
216              
217 0     0 1   sub user_agent { $UA }
218              
219             =head1 SEE ALSO
220              
221             L, L
222              
223             =head1 AUTHORS
224              
225             brian d foy, C<< >>
226              
227             Maintained by Nigel Horne, C<< >>
228              
229             =head1 SUPPORT
230              
231             This module is provided as-is without any warranty.
232              
233             You can find documentation for this module with the perldoc command.
234              
235             perldoc Test::HTTPStatus
236              
237             You can also look for information at:
238              
239             =over 4
240              
241             =item * MetaCPAN
242              
243             L
244              
245             =item * RT: CPAN's request tracker
246              
247             L
248              
249             =item * CPANTS
250              
251             L
252              
253             =item * CPAN Testers' Matrix
254              
255             L
256              
257             =item * CPAN Testers Dependencies
258              
259             L
260              
261             =back
262              
263             =head1 LICENSE AND COPYRIGHT
264              
265             This program is released under the following licence: GPL2
266             Copyright © 2002-2019, brian d foy . All rights reserved.
267              
268             This program is free software; you can redistribute it and/or modify
269             it under the terms of the Artistic License 2.0.
270              
271             =cut
272              
273             1;