File Coverage

blib/lib/Test/WWW/Mechanize/JSON.pm
Criterion Covered Total %
statement 15 68 22.0
branch 0 14 0.0
condition 0 16 0.0
subroutine 5 19 26.3
pod 10 12 83.3
total 30 129 23.2


line stmt bran cond sub pod time code
1 1     1   27450 use strict;
  1         3  
  1         40  
2 1     1   6 use warnings;
  1         1  
  1         60  
3            
4             package Test::WWW::Mechanize::JSON;
5            
6             our $VERSION = 0.73;
7            
8 1     1   6 use base "Test::WWW::Mechanize";
  1         7  
  1         1663  
9 1     1   287995 use Test::More;
  1         2  
  1         13  
10 1     1   1846 use JSON::Any;
  1         53137  
  1         83  
11            
12            
13             =head1 NAME
14            
15             Test::WWW::Mechanize::JSON - Add a JSON and AJAXy methods to the super-class
16            
17             =head1 SYNOPSIS
18            
19             use Test::More 'no_plan';
20             use_ok("Test::WWW::Mechanize::JSON") or BAIL_OUT;
21             my $MECH = Test::WWW::Mechanize::JSON->new(
22             noproxy => 1,
23             etc => 'other-params-for-Test::WWW::Mechanize',
24             );
25             $MECH->get('http://example.com/json');
26             my $json_as_perl = $MECH->json_ok or BAIL_OUT Dumper $MECH->response;
27             $MECH->diag_json;
28            
29             =head1 DESCRIPTION
30            
31             Extends L
32             to test JSON content in response bodies and C headers.
33            
34             It adds a few HTTP verbs to Mechanize, for convenience.
35            
36             =head2 METHODS: HTTP VERBS
37            
38             =cut
39            
40             =head3 $mech->put
41            
42             An HTTP 'put' request, extending L.
43            
44             At the time of wriring, modules that rely on L
45             treat C as a type of C, when the spec says it is really a type of C:
46            
47             The fundamental difference between the POST and PUT
48             requests is reflected in the different meaning of
49             the Request-URI.
50             HTTP specification
51            
52             =cut
53            
54             sub put {
55 0     0 1   my ($self, @parameters) = @_;
56 0           my @suff = $self->_process_colonic_headers(\@parameters,1);
57            
58 0           require HTTP::Request::Common;
59 0           my $r = HTTP::Request::Common::POST(@parameters);
60 0           $r->{_method} = 'PUT';
61 0           return $self->request( $r, @suff );
62             }
63            
64            
65             =head3 $mech->delete
66            
67             An HTTP 'delete' request, extending L.
68            
69             =cut
70            
71             sub delete {
72 0     0 1   require HTTP::Request::Common;
73 0           my ($self, @parameters) = @_;
74 0           my @suff = $self->_process_colonic_headers(\@parameters,1);
75 0           return $self->request( HTTP::Request::Common::DELETE( @parameters ), @suff );
76             }
77            
78            
79             =head3 $mech->options
80            
81             An HTTP 'options' request, extending L.
82            
83             =cut
84            
85             sub options {
86 0     0 1   require HTTP::Request::Common;
87 0           my ($self, @parameters) = @_;
88 0           my @suff = $self->_process_colonic_headers(\@parameters,1);
89 0           return $self->request( HTTP::Request::Common::_simple_req( 'OPTIONS', @parameters ), @suff );
90             }
91            
92            
93             =head3 $mech->head
94            
95             An HTTP 'head' request, using L.
96            
97             =cut
98            
99             sub head {
100 0     0 1   require HTTP::Request::Common;
101 0           my ($self, @parameters) = @_;
102 0           my @suff = $self->_process_colonic_headers(\@parameters,1);
103 0           return $self->request( HTTP::Request::Common::_simple_req( 'HEAD', @parameters ), @suff );
104             }
105            
106             =head2 METHODS: ASSERTIONS
107            
108             =head3 $mech->json_ok($desc)
109            
110             Tests that the last received resopnse body is valid JSON.
111            
112             A default description of "Got JSON from $url"
113             or "Not JSON from $url"
114             is used if none if provided.
115            
116             Returns the L object, that you may perform
117             further tests upon it.
118            
119             =cut
120            
121             sub json_ok {
122 0     0 1   my ($self, $desc) = @_;
123 0           return $self->_json_ok( $desc, $self->content );
124             }
125            
126            
127             =head3 $mech->x_json_ok($desc)
128            
129             As C<$mech->json_ok($desc)> but examines the C header.
130            
131             =cut
132            
133             sub x_json_ok {
134 0     0 1   my ($self, $desc) = @_;
135 0           return $self->_json_ok(
136             $desc,
137             $self->response->headers->{'x-json'}
138             );
139             }
140            
141             sub json {
142 0     0 0   my ($self, $text) = @_;
143 0 0 0       $text ||= exists $self->response->headers->{'x-json'}?
144             $self->response->headers->{'x-json'}
145             : $self->content;
146 0           my $json = eval {
147 0           JSON::Any->jsonToObj($text);
148             };
149 0           return $json;
150             }
151            
152             =head2 any_json_ok( $desc )
153            
154             Like the other JSON methods, but passes if the response
155             contained JSON in the content or C header.
156            
157             =cut
158            
159             sub any_json_ok {
160 0     0 1   my ($self, $desc) = @_;
161 0           return $self->_json_ok(
162             $desc,
163             $self->json
164             );
165             }
166            
167            
168             sub _json_ok {
169 0     0     my ($self, $desc, $text) = @_;
170 0           my $json = $self->json( $text );
171            
172 0 0         if (not $desc){
173 0 0 0       if (defined $json and ref $json eq 'HASH' and not $@){
      0        
174 0           $desc = sprintf 'Got JSON from %s', $self->uri;
175             }
176             else {
177 0           $desc = sprintf 'Not JSON from %s (%s)', $self->uri, $@;
178             }
179             }
180            
181 0           Test::Builder->new->ok( $json, $desc );
182            
183 0   0       return $json || undef;
184             }
185            
186            
187             =head3 $mech->diag_json
188            
189             Like L, but renders the JSON of body the last request
190             with indentation.
191            
192             =cut
193            
194             sub diag_json {
195 0     0 1   my $self = shift;
196 0           return $self->_diag_json( $self->content );
197             }
198            
199             =head3 $mech->diag_x_json
200            
201             Like L, but renders the JSON
202             from the C header of the last request with indentation.
203            
204             =cut
205            
206             sub diag_x_json {
207 0     0 1   my $self = shift;
208 0           return $self->_diag_json(
209             $self->response->headers->{'x-json'}
210             );
211             }
212            
213             sub _diag_json {
214 0     0     my ($self, $text) = @_;
215 0           eval {
216 0           my $json = $self->json( $text );
217 0 0 0       if (not defined $json){
    0          
218 0           warn "Not a $json objet";
219             }
220             elsif (not ref $json or ref $json ne 'HASH'){
221 0           warn "Not an JSON object";
222             }
223             else {
224 0           warn "Not a JSON object?";
225             }
226             };
227 0 0         warn $@ if $@;
228             }
229            
230            
231             sub utf8 {
232 0 0   0 0   return $_[0]->response->headers('content-type') =~ m{charset=\s*utf-8}? 1 : 0;
233             }
234            
235             =head3 $mech->utf8_ok( $desc )
236            
237             Passes if the last response contained a C definition in its content-type header.
238            
239             =cut
240            
241             sub utf8_ok {
242 0     0 1   my $self = shift;
243 0   0       my $desc = shift || 'Has a utf-8 heaer';
244 0           Test::Builder->new->ok( $self->utf8, $desc );
245             }
246            
247            
248            
249            
250            
251             1;
252            
253             =head1 AUTHOR AND COPYRIGHT
254            
255             Copyright (C) Lee Goddard, 2009/2011.
256            
257             Available under the same terms as Perl itself.
258            
259             =cut
260            
261             1;