File Coverage

blib/lib/JSON/Assert.pm
Criterion Covered Total %
statement 98 134 73.1
branch 34 70 48.5
condition 6 18 33.3
subroutine 14 16 87.5
pod 8 8 100.0
total 160 246 65.0


line stmt bran cond sub pod time code
1             ## ----------------------------------------------------------------------------
2             # Copyright (C) 2014-2016 NZRS Ltd
3             ## ----------------------------------------------------------------------------
4             package JSON::Assert;
5              
6 6     6   102752 use Moo;
  6         84613  
  6         44  
7 6     6   18923 use MooX::Types::MooseLike::Base 'Str';
  6         49338  
  6         818  
8 6     6   5126 use JSON::Path;
  6         153577  
  6         98  
9 6     6   5345 use Test::Deep::NoTest;
  6         57662  
  6         62  
10              
11             $JSON::Path::Safe = 0;
12              
13             our $VERSION = '0.08';
14             our $VERBOSE = $ENV{JSON_ASSERT_VERBOSE} || 1;
15              
16             has 'error' =>
17             is => "rw",
18             isa => Str,
19             clearer => "_clear_error",
20             ;
21              
22             sub _self {
23 26     26   69 my $args = shift;
24 26 100       138 if ( ref $args->[0] eq __PACKAGE__ ) {
    50          
25 22         71 return shift @$args;
26             }
27             elsif ( $args->[0] eq __PACKAGE__ ) {
28 4         14 return do { shift @$args }->new();
  4         139  
29             }
30 0         0 return __PACKAGE__->new();
31             }
32              
33             # assert_jpath_count
34             sub assert_jpath_count {
35 9     9 1 64 my $self = _self(\@_);
36 9         1334 my ($doc, $jpath_str, $count) = @_;
37              
38 9         46 my $jpath = _parse_jpath($jpath_str);
39              
40 9         48 my @values = $jpath->values($doc);
41              
42 9         15230 my $found = 0;
43 9 100       60 if (scalar @values != 1) {
    100          
44 5         13 $found = scalar @values;
45             }
46             elsif (ref $values[0] eq 'ARRAY') {
47 3         10 $found = scalar @{$values[0]};
  3         11  
48             }
49             else {
50 1         5 $found = 1;
51             }
52              
53 9 50       2300 print "assert_jpath_count: Found $found\n" if $VERBOSE;
54              
55 9 100       71 unless ( $found == $count ) {
56 3         38 die "JPath '$jpath' has $found " . $self->_plural($found, 'value') . ", not $count as expected";
57             }
58              
59 6         48 return 1;
60             }
61              
62             sub is_jpath_count {
63 7     7 1 2516 my $self = _self(\@_);
64 7         30 my ($doc, $jpath, $count) = @_;
65              
66 7         311 $self->_clear_error();
67 7         71 eval { $self->assert_jpath_count($doc, $jpath, $count) };
  7         29  
68 7 100       39 if ( $@ ) {
69 1         37 $self->error($@);
70 1         79 return;
71             }
72 6         54 return 1;
73             }
74              
75             # assert_jpath_value_match
76             sub assert_jpath_value_match {
77 4     4 1 31 my $self = _self(\@_);
78 4         68 my ($doc, $jpath_str, $match) = @_;
79              
80 4         19 my $jpath = _parse_jpath($jpath_str);
81            
82             # firstly, check that the node actually exists
83 4         22 my @values = $jpath->values($doc);
84              
85 4         7152 my $found = 0;
86 4 50       28 if (scalar @values != 1) {
    100          
87 0         0 $found = scalar @values;
88             }
89             elsif (ref $values[0] eq 'ARRAY') {
90 1         4 $found = scalar @{$values[0]};
  1         5  
91             }
92             else {
93 3         9 $found = 1;
94             }
95              
96 4 50       835 print "assert_jpath_value_match: Found $found\n" if $VERBOSE;
97 4 100       31 unless ( $found == 1 ) {
98 1         10 die "JPath '$jpath' matched $found values when we expected to match one";
99             }
100              
101             # check the value is what we expect
102 3         11 my $value = $values[0];
103 3 50       327 print "assert_jpath_value_match: This value's value : " . $value . "\n" if $VERBOSE;
104 3 0 66     34 return 1 if (ref($value) eq ref($match) && ref($value) eq 'HASH' && scalar(keys(%$value)) == 0 && scalar(keys(%$match)) == 0);
      33        
      33        
105 3 100       35 unless ( $value =~ $match ) {
106 1         11 die "JPath '$jpath' doesn't match '$match' as expected, instead it is '" . $value . "'";
107             }
108              
109 2         15 return 1;
110             }
111              
112             sub does_jpath_value_match {
113 2     2 1 1559 my $self = _self(\@_);
114 2         5 my ($doc, $jpath_str, $match) = @_;
115              
116 2         45 $self->_clear_error();
117 2         15 eval { $self->assert_jpath_value_match($doc, $jpath_str, $match) };
  2         7  
118 2 50       6 if ( $@ ) {
119 0         0 $self->error($@);
120 0         0 return;
121             }
122 2         12 return 1;
123             }
124              
125             # assert_jpath_values_match
126             sub assert_jpath_values_match {
127 2     2 1 7 my $self = _self(\@_);
128 2         6 my ($doc, $jpath_str, $match) = @_;
129              
130 2         6 my $jpath = _parse_jpath($jpath_str);
131              
132             # firstly, check that the node actually exists
133 2         8 my @values = $jpath->values($doc);
134              
135 2         2854 my $values;
136 2 100       11 if (scalar @values != 1) {
    50          
137 1         3 $values = \@values;
138             }
139             elsif (ref $values[0] eq 'ARRAY') {
140 0         0 $values = $values[0];
141             }
142             else {
143 1         4 $values = \@values;
144             }
145            
146 2 50       377 print 'assert_jpath_values_match: Found ' . (scalar @$values) . "\n" if $VERBOSE;
147 2 50       12 unless ( @$values ) {
148 0         0 die "JPath '$jpath' matched no nodes when we expected to match at least one";
149             }
150              
151             # check the values are what we expect
152 2         6 my $i = 0;
153 2         4 foreach my $value ( @$values ) {
154 4 50       324 print "assert_jpath_value_match: This keys's value : " . $value . "\n" if $VERBOSE;
155 4 0 33     29 if (ref($value) eq ref($match) && ref($value) eq 'HASH' && scalar(keys(%$value)) == 0 && scalar(keys(%$match)) == 0){
      33        
      0        
156 0         0 $i++;
157 0         0 next;
158             }
159 4 50       34 unless ( $value =~ $match ) {
160 0         0 die "Item $i of JPath '$jpath' doesn't match '$match' as expected, instead it is '" . $value . "'";
161             }
162 4         10 $i++;
163             }
164              
165 2         15 return 1;
166             }
167              
168             sub do_jpath_values_match {
169 2     2 1 1656 my $self = _self(\@_);
170 2         7 my ($doc, $jpath_str, $match) = @_;
171              
172 2         53 $self->_clear_error();
173 2         18 eval { $self->assert_jpath_values_match($doc, $jpath_str, $match) };
  2         7  
174 2 50       5 if ( $@ ) {
175 0         0 $self->error($@);
176 0         0 return;
177             }
178 2         13 return 1;
179             }
180              
181             sub assert_json_contains {
182 0     0 1 0 my $self = _self(\@_);
183 0         0 my ($doc, $jpath_str, $match) = @_;
184              
185 0         0 my $jpath = _parse_jpath($jpath_str);
186 0         0 my @values = $jpath->values($doc);
187              
188 0 0       0 if (ref $match eq 'HASH') {
    0          
189 0 0       0 if (! eq_deeply($values[0], superhashof($match))) {
190 6     6   13849 use Data::Dumper;
  6         40816  
  6         2591  
191 0 0       0 if ($VERBOSE) {
192 0         0 print "wanted: " . Dumper($match) . ", got: " . Dumper ($values[0]) . "\n";
193             }
194              
195             }
196             }
197             elsif (ref $match eq 'ARRAY') {
198 0 0       0 if (ref $match->[0] eq 'HASH') {
199 0         0 my @new_wanted = map { superhashof($_) } @$match;
  0         0  
200              
201 0 0       0 die "JPath '$jpath_str' doesn't match wanted data structure"
202             unless eq_deeply(@values, \@new_wanted);
203             }
204              
205 0 0       0 die "JPath '$jpath_str' doesn't match wanted data structure"
206             unless eq_deeply($values[0], $match);
207             }
208             else {
209 0 0       0 die "JPath '$jpath_str' doesn't match wanted data structure"
210             unless $values[0] eq $match;
211             }
212              
213 0         0 return 1;
214             }
215              
216             sub does_jpath_contains {
217 0     0 1 0 my $self = _self(\@_);
218 0         0 my ($doc, $jpath_str, $match) = @_;
219              
220 0         0 $self->_clear_error();
221 0         0 eval { $self->assert_json_contains($doc, $jpath_str, $match) };
  0         0  
222 0 0       0 if ( $@ ) {
223 0         0 $self->error($@);
224 0         0 return;
225             }
226 0         0 return 1;
227             }
228              
229              
230             # private functions
231             sub _plural {
232 3     3   66 my ($class, $number, $single, $plural) = @_;
233              
234 3 50       102 return $number == 1 ? $single : defined $plural ? $plural : "${single}s";
    100          
235             }
236              
237             sub _parse_jpath {
238 15     15   51 my ($jpath_str) = @_;
239              
240 15         111 my $jpath = JSON::Path->new($jpath_str);
241 15 50       215 if ($@) {
242 0         0 die "Error evaluating json path ($jpath_str): $@";
243             }
244              
245 15         45 return $jpath;
246             }
247            
248              
249             1;
250             __END__