File Coverage

blib/lib/RPC/ExtDirect/Test/Util.pm
Criterion Covered Total %
statement 54 65 83.0
branch 14 24 58.3
condition 1 3 33.3
subroutine 12 14 85.7
pod 0 8 0.0
total 81 114 71.0


line stmt bran cond sub pod time code
1             package RPC::ExtDirect::Test::Util;
2              
3 34     34   443129 use strict;
  34         51  
  34         852  
4 34     34   114 use warnings;
  34         38  
  34         735  
5 34     34   103 no warnings 'uninitialized';
  34         43  
  34         1417  
6              
7 34     34   112 use base 'Exporter';
  34         37  
  34         2839  
8              
9 34     34   1206 use Test::More;
  34         25306  
  34         152  
10 34     34   24808 use JSON;
  34         330701  
  34         731  
11              
12             our @EXPORT = qw/
13             ref_ok
14             is_deep
15             cmp_api
16             prepare_input
17             /;
18              
19             our @EXPORT_OK = qw/
20             cmp_json
21             /;
22              
23             ### EXPORTED PUBLIC PACKAGE SUBROUTINE ###
24             #
25             # Replacement for isa_ok that actually checks that wanted value
26             # is a blessed object and not a string with package name. :(
27             #
28              
29             sub ref_ok {
30 38     38 0 24260 my ($have, $want, $desc) = @_;
31              
32 38 100       145 $desc = "Object isa $want" unless $desc;
33              
34 38 50 33     329 ok( (ref $have eq $want) && $have->isa($want), $desc )
35             or diag explain "Expected '", $have, "' to be an object blessed into ",
36             $want, " package";
37             }
38              
39             ### EXPORTED PUBLIC PACKAGE SUBROUTINE ###
40             #
41             # A wrapper around Test::More::is_deeply() that will print
42             # the diagnostics if a test fails
43             #
44              
45             sub is_deep {
46 303 50   303 0 96522 is_deeply @_ or diag explain "Expected: ", $_[1], "Actual: ", $_[0];
47             }
48              
49             ### EXPORTED PUBLIC PACKAGE SUBROUTINE ###
50             #
51             # Compare two JavaScript API declarations
52             #
53              
54             sub cmp_api {
55             # This can be called either as a class method, or a plain sub
56 8 50   8 0 3649 shift if $_[0] eq __PACKAGE__;
57            
58 8         19 my ($have, $want, $desc) = @_;
59            
60 8 50       33 $have = deparse_api($have) unless ref $have;
61 8 50       25 $want = deparse_api($want) unless ref $want;
62            
63 8         19 is_deep $have, $want, $desc;
64             }
65              
66             ### EXPORTED PUBLIC PACKAGE SUBROUTINE ###
67             #
68             # Compare two strings ignoring the whitespace
69             #
70              
71             sub cmp_str {
72             # This can be called either as a class method, or a plain sub
73 0 0   0 0 0 shift if $_[0] eq __PACKAGE__;
74            
75 0         0 my ($have, $want, $desc) = @_;
76            
77 0         0 $_ =~ s/\s//g for ($have, $want);
78            
79 0         0 is $have, $want, $desc;
80             }
81              
82             ### EXPORTED PUBLIC PACKAGE SUBROUTINE ###
83             #
84             # Compare two JSON structures, ignoring the whitespace
85             #
86              
87             sub cmp_json {
88             # This can be called either as a class method, or a plain sub
89 28 50   28 0 17330 shift if $_[0] eq __PACKAGE__;
90            
91 28         46 my ($have_json, $want_json, $desc) = @_;
92            
93 28         204 $_ =~ s/\s//g for ($have_json, $want_json);
94            
95 28         67 my $have = JSON::from_json($have_json);
96 28         518 my $want = JSON::from_json($want_json);
97            
98 28         275 is_deep $have, $want, $desc;
99             }
100              
101             ### NON EXPORTED PUBLIC PACKAGE SUBROUTINE ###
102             #
103             # Deparse and normalize a JavaScript string with Ext.Direct API
104             # declaration into Perl data structures suitable for deep comparison
105             #
106              
107             sub deparse_api {
108 16     16 0 18 my ($api_str) = @_;
109            
110 16         4959 $api_str =~ s/\s*//gms;
111              
112 16         93 my @parts = split /;\s*/, $api_str;
113              
114 16         30 for my $part ( @parts ) {
115 40 100       94 next unless $part =~ /=\{/;
116              
117 26         77 my ($var, $json) = split /=/, $part;
118            
119 26         63 my $api_def = JSON::from_json($json);
120            
121 26         673 my $actions = sort_action_methods($api_def->{actions});
122              
123 26 100       51 if ( defined $actions ) {
124 16         33 $api_def->{actions} = $actions;
125             }
126              
127 26         73 $part = { $var => $api_def };
128             }
129              
130 16         31 return [ @parts ];
131             }
132              
133             ### EXPORTED PUBLIC PACKAGE SUBROUTINE ###
134             #
135             # Convert a test input hashref into the actual object
136             #
137              
138             sub prepare_input {
139 0     0 0 0 my ($mod, $input) = @_;
140            
141 0 0       0 return $input unless ref $input;
142            
143             # Package name should be in the RPC::ExtDirect::Test::Util namespace
144 0         0 my $pkg = __PACKAGE__.'::'.$mod;
145            
146             # Convertor sub name goes first
147 0         0 my $conv = $input->{type};
148 0         0 my $arg = $input->{arg};
149            
150             # Calling the sub as a class method is easier
151             # than taking its ref, blah blah
152 0         0 my $result = $pkg->$conv(@$arg);
153            
154 0         0 return $result;
155             }
156              
157             ### NON EXPORTED PUBLIC PACKAGE SUBROUTINE ###
158             #
159             # Sort the Method hashrefs on an Action object
160             #
161              
162             sub sort_action_methods {
163 26     26 0 35 my ($api_href) = @_;
164              
165             # %$api_href will auto-vivify if $api_href is undef
166             # This can bite your ass.
167 26 100       49 return unless $api_href;
168            
169 16         17 my $new_href = {};
170            
171             # map() looks too unwieldy here
172 16         40 for my $action_name ( keys %$api_href ) {
173 52         36 my @methods = @{ $api_href->{ $action_name } };
  52         76  
174            
175             $new_href->{ $action_name }
176 52         70 = [ sort { $a->{name} cmp $b->{name} } @methods ];
  542         468  
177             }
178            
179 16         21 return $new_href;
180             }
181              
182             1;
183