File Coverage

blib/lib/Test/WWW/Stub.pm
Criterion Covered Total %
statement 72 73 98.6
branch 11 12 91.6
condition 5 8 62.5
subroutine 25 26 96.1
pod 7 7 100.0
total 120 126 95.2


line stmt bran cond sub pod time code
1             package Test::WWW::Stub;
2 2     2   176258 use 5.010;
  2         15  
3 2     2   12 use strict;
  2         6  
  2         37  
4 2     2   9 use warnings;
  2         4  
  2         72  
5              
6             our $VERSION = "0.08";
7              
8 2     2   12 use Carp ();
  2         7  
  2         39  
9 2     2   869 use Guard; # guard
  2         911  
  2         102  
10 2     2   887 use LWP::Protocol::PSGI;
  2         71788  
  2         69  
11 2     2   472 use Plack::Request;
  2         56300  
  2         50  
12 2     2   12 use Test::More ();
  2         4  
  2         38  
13 2     2   1087 use List::MoreUtils ();
  2         24389  
  2         54  
14 2     2   15 use URI;
  2         4  
  2         43  
15              
16 2     2   889 use Test::WWW::Stub::Intercepter;
  2         5  
  2         1903  
17              
18             my $Intercepter = Test::WWW::Stub::Intercepter->new;
19             our @Requests;
20              
21             my $register_g;
22             my $app;
23 0     0   0 sub _app { $app; }
24              
25             $app = sub {
26             my ($env) = @_;
27             my $req = Plack::Request->new($env);
28              
29             push @Requests, $req;
30              
31             my $uri = _normalize_uri($req->uri);
32              
33             my $stubbed_res = $Intercepter->intercept($uri, $env, $req);
34             return $stubbed_res if $stubbed_res;
35              
36             my ($file, $line) = _trace_file_and_line();
37              
38             my $method = $req->method;
39             warn "Unexpected external access: $method $uri at $file line $line";
40              
41             return [ 499, [], [] ];
42             };
43              
44             sub import {
45 3   66 3   2455 $register_g //= LWP::Protocol::PSGI->register($app);
46             }
47              
48             sub register {
49 12     12 1 28560 my ($class, $uri_or_re, $app_or_res) = @_;
50 12   50     47 $app_or_res //= [200, [], []];
51 12         51 my $old_handler = $Intercepter->get_handler($uri_or_re);
52              
53 12         45 $Intercepter->register($uri_or_re, $app_or_res);
54             defined wantarray && return guard {
55 11 100   11   12205 if ($old_handler) {
56 2         8 $Intercepter->register($uri_or_re, $old_handler);
57             } else {
58 9         42 $Intercepter->unregister($uri_or_re);
59             }
60 12 100       103 };
61             }
62              
63             sub last_request {
64 2 100   2 1 1729 return undef unless @Requests;
65 1         6 return $Requests[-1];
66             }
67              
68             sub last_request_for {
69 3     3 1 7053 my ($class, $method, $url) = @_;
70 3         8 my $reqs = { map { _request_signature($_) => $_ } @Requests };
  9         87  
71 3         49 my $signature = "$method $url";
72 3         13 return $reqs->{$signature};
73             }
74              
75             sub _request_signature {
76 9     9   15 my ($req) = @_;
77 9         21 my $normalized = _normalize_uri($req->uri);
78 9         30 return join ' ', $req->method, $normalized;
79             }
80              
81             # Don't use query part of URI for handler matching.
82             sub _normalize_uri {
83 36     36   8725 my ($uri) = @_;
84 36         103 my $cloned = $uri->clone;
85 36         280 $cloned->query(undef);
86 36         611 return $cloned;
87             }
88              
89 3     3 1 745 sub requests { @Requests }
90              
91             sub requested_ok {
92 3     3 1 9658 my ($class, $method, $url) = @_;
93 3         6 local $Test::Builder::Level = $Test::Builder::Level + 1;
94             Test::More::ok(
95             List::MoreUtils::any(sub {
96 5     5   35 my $req_url = _normalize_uri($_->uri);
97 5 100       20 $_->method eq $method && $req_url eq $url
98             }, @Requests),
99             "stubbed $method $url",
100 3 100       30 ) or Test::More::diag Test::More::explain [ map { $_->method . ' ' . $_->uri } @Requests ]
  4         1364  
101             }
102              
103             sub clear_requests {
104 3     3 1 7598 @Requests = ();
105             }
106              
107             sub _trace_file_and_line {
108 4     4   9 my $level = $Test::Builder::Level;
109 4         31 my (undef, $file, $line) = caller($level);
110             # assume "Actual" caller is test file named FOOBAR.t
111 4   66     32 while ($file && $file !~ m<\.t$>) {
112 32         189 (undef, $file, $line) = caller(++$level);
113             }
114 4         16 ($file, $line);
115             }
116              
117             sub unstub {
118 4 50   4 1 21897 Carp::croak 'guard is required' unless defined wantarray;
119 4         28 undef $register_g;
120             return guard {
121 4     4   755362 $register_g = LWP::Protocol::PSGI->register($app);
122             }
123 4         298 }
124              
125             1;
126             __END__