File Coverage

blib/lib/RPC/ExtDirect/Test/Util.pm
Criterion Covered Total %
statement 51 62 82.2
branch 11 20 55.0
condition n/a
subroutine 11 13 84.6
pod 0 7 0.0
total 73 102 71.5


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