File Coverage

blib/lib/Test/Mock/HTTP/Tiny.pm
Criterion Covered Total %
statement 42 56 75.0
branch 5 12 41.6
condition 1 3 33.3
subroutine 13 16 81.2
pod 7 7 100.0
total 68 94 72.3


line stmt bran cond sub pod time code
1             package Test::Mock::HTTP::Tiny;
2              
3 1     1   74273 use strict;
  1         2  
  1         26  
4 1     1   6 use warnings;
  1         2  
  1         46  
5              
6             # ABSTRACT: Record and replay HTTP requests/responses with HTTP::Tiny
7              
8             our $VERSION = '0.002'; # VERSION
9              
10 1     1   907 use Data::Dumper;
  1         8521  
  1         61  
11 1     1   10 use HTTP::Tiny;
  1         2  
  1         21  
12 1     1   617 use Test::Deep::NoTest;
  1         10129  
  1         8  
13 1     1   1169 use URI::Escape;
  1         1292  
  1         276  
14              
15              
16             my $captured_data = [];
17             my $mocked_data = [];
18              
19              
20             sub mocked_data {
21 5     5 1 866 return $mocked_data;
22             }
23              
24              
25             sub set_mocked_data {
26 1     1 1 2 my ($class, $new_mocked_data) = @_;
27              
28 1 50       6 if (ref($new_mocked_data) eq 'ARRAY') {
    0          
29             # An arrayref of items was provided
30 1         3 $mocked_data = [ @$new_mocked_data ];
31             }
32             elsif (ref($new_mocked_data) eq 'HASH') {
33             # A single item was provided
34 0         0 $mocked_data = [ { %$mocked_data } ];
35             }
36             else {
37             # TODO: error
38             }
39             }
40              
41              
42             sub append_mocked_data {
43 1     1 1 2 my ($class, $new_mocked_data) = @_;
44              
45 1 50       8 if (ref($new_mocked_data) eq 'ARRAY') {
    50          
46             # Multiple items are being appended
47 0         0 push @$mocked_data, @$new_mocked_data;
48             }
49             elsif (ref($new_mocked_data) eq 'HASH') {
50             # Single item is being appended
51 1         7 push @$mocked_data, { %$new_mocked_data };
52             }
53             else {
54             # TODO: error
55             }
56             }
57              
58              
59             sub clear_mocked_data {
60 1     1 1 24 $mocked_data = [];
61             }
62              
63              
64             sub captured_data {
65 0     0 1 0 return $captured_data;
66             }
67              
68              
69             sub captured_data_dump {
70 0     0 1 0 local $Data::Dumper::Deepcopy = 1;
71 0         0 return Dumper $captured_data;
72             }
73              
74              
75             sub clear_captured_data {
76 0     0 1 0 $captured_data = [];
77             }
78              
79             {
80             ## no critic
81 1     1   6 no strict 'refs';
  1         2  
  1         29  
82 1     1   5 no warnings 'redefine';
  1         2  
  1         330  
83             my $_HTTP_Tiny__request = \&HTTP::Tiny::_request;
84             *{"HTTP::Tiny::_request"} = sub {
85 1     1   124 my ($self, $method, $url, $args) = @_;
86              
87 1         3 my $normalized_args = { %$args };
88              
89 1 50 33     23 if (exists $args->{headers}{'content-type'} &&
90             $args->{headers}{'content-type'} eq
91             'application/x-www-form-urlencoded')
92             {
93             # Unescape form data
94 0         0 $normalized_args->{content} = {};
95              
96 0         0 for my $param (split(/&/, $args->{content})) {
97             my ($name, $value) =
98 0         0 map { uri_unescape($_) } split(/=/, $param, 2);
  0         0  
99 0         0 $normalized_args->{content}{$name} = $value;
100             }
101             }
102              
103 1         3 for my $i (0 .. $#{$mocked_data}) {
  1         3  
104 1         3 my $mock_req = $mocked_data->[$i];
105              
106             next if !eq_deeply(
107 1 50       9 [ $mock_req->{method}, $mock_req->{url}, $mock_req->{args} ],
108             [ $method, $url, $normalized_args ]
109             );
110              
111             # Found a matching request in mocked data
112 1         15984 $mock_req = { %$mock_req };
113              
114             # Remove the request from mocked data so that it's not used again
115 1         5 splice(@$mocked_data, $i, 1);
116              
117             # Return the corresponding response
118 1         9 return $mock_req->{response};
119             }
120              
121             # No matching request found -- call the actual HTTP::Tiny request method
122 0           my $response = &$_HTTP_Tiny__request($self, $method, $url, $args);
123              
124             # Save the request/response in captured data
125 0           push @$captured_data, {
126             method => $method,
127             url => $url,
128             args => $normalized_args,
129             response => $response,
130             };
131            
132 0           return $response;
133             };
134             }
135              
136             1;
137              
138             __END__