File Coverage

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