File Coverage

blib/lib/HTML/Tested/Test.pm
Criterion Covered Total %
statement 132 135 97.7
branch 27 32 84.3
condition 21 29 72.4
subroutine 30 31 96.7
pod 1 12 8.3
total 211 239 88.2


line stmt bran cond sub pod time code
1 17     17   212680 use strict;
  17         46  
  17         848  
2 17     17   239 use warnings FATAL => 'all';
  17         100  
  17         1102  
3              
4             package HTML::Tested::Test;
5 17     17   118 use base 'Exporter';
  17         31  
  17         2198  
6 17     17   1810 use Data::Dumper;
  17         17612  
  17         1133  
7 17     17   26868 use Text::Diff;
  17         275994  
  17         1850  
8 17     17   219 use Carp;
  17         48  
  17         23432  
9              
10             our @EXPORT_OK = qw(Register_Widget_Tester Stash_Mismatch Ensure_Value_To_Check);
11              
12             sub Stash_Mismatch {
13 18     18 0 47 my ($n, $res, $v) = @_;
14 18 100       385 my $ret = sprintf("Mismatch at %s: got %s, expected %s",
    100          
15             $n, defined($res) ? "\"$res\"" : "undef",
16             defined($v) ? "\"$v\"" : "undef");
17 18 100 100     473 goto OUT unless (defined($res) && defined($v)
      100        
      66        
18             && $res =~ /\n.*\n/ms && $v =~ /\n.*\n/ms);
19 1         7 $ret .= ". The diff is\n" . diff(\$v, \$res);
20 18         452 OUT:
21             return $ret;
22             }
23              
24             sub Ensure_Value_To_Check {
25 84     84 0 170 my ($r_stash, $name, $e_val, $errs) = @_;
26 84         169 my $r_val = $r_stash->{$name};
27 84 50 66     321 return if (!defined($r_val) && !defined($e_val));
28              
29 84 100 50     444 if (defined($r_val) xor defined($e_val)) {
30 3         11 push @$errs, Stash_Mismatch($name, $r_val, $e_val);
31 3         12 return;
32             }
33 81         396 return $r_val;
34             }
35              
36             sub compare_stashes {
37 80     80 0 636 my ($class, $e_root, $stash, $e_stash) = @_;
38 80 0 33     247 return () if (!defined($stash) && !defined($e_stash));
39 80 100 50     493 if (defined($stash) xor defined($e_stash)) {
40 1         7 return ("Stash " . Dumper($stash)
41             . "differ from "
42             . "expected " . Dumper($e_stash));
43             }
44 79         423 return $class->_run_checks('stash', $e_root, $stash, $e_stash);
45             }
46              
47             sub _run_checks {
48 106     106   226 my ($class, $check, $e_root, $res, $e_stash) = @_;
49 106         541 my $f = "check_$check";
50 104         967 return map {
51 106         356 $_->__ht_tester->$f($e_root, $_->name, $e_stash, $res);
52 106         225 } @{ $e_root->Widgets_List };
53             }
54              
55             sub compare_text_to_stash {
56 27     27 0 141 my ($class, $e_root, $text, $e_stash) = @_;
57 27         107 return $class->_run_checks('text', $e_root, $text, $e_stash);
58             }
59              
60             my $_index = 0;
61              
62             sub Make_Expected_Class {
63 105     105 0 201 my ($target_class, $expected) = @_;
64 105         373 my $package = "$target_class\::__HT_TESTER_" . $_index++;
65             {
66 17     17   151 no strict 'refs';
  17         67  
  17         24955  
  105         136  
67 105         132 push @{ *{ "$package\::ISA" } }, $target_class
  105         2418  
  105         1402  
68 105 50       132 unless @{ *{ "$package\::ISA" } };
  105         132  
69             };
70 105         544 my $wl = $target_class->Widgets_List;
71 152         591 $package->Widgets_List([ grep {
72 105         1448 exists($expected->{ $_->name });
73             } @$wl ]);
74 105         4751 return $package;
75             }
76              
77             sub bless_unknown_widget {
78 2     2 0 7 my ($class, $n, $v, $err) = @_;
79 2         8 push @$err, "Unknown widget $n found in expected!";
80 2         12 return $v;
81             }
82            
83             sub bless_from_tree_for_test {
84 105     105 0 340 my ($class, $target, $expected, $err) = @_;
85 105         203 my $res = {};
86 105         163 my (@disabled, %e, @reverted, @sealed, @unsorted);
87 105         539 while (my ($n, $v) = each %$expected) {
88 104         275 my $rev = ($n =~ s/^HT_NO_//);
89 104         474 my $sealed = ($n =~ s/^HT_SEALED_//);
90 104         192 my $unsorted = ($n =~ s/^HT_UNSORTED_//);
91 104 100       252 push @reverted, $n if $rev;
92 104 100       357 push @sealed, $n if $sealed;
93 104 100       236 push @unsorted, $n if $unsorted;
94 104         508 $e{$n} = $v;
95             }
96 105         186 $expected = \%e;
97              
98 105         304 my $e_class = Make_Expected_Class($target, $expected);
99 105         493 while (my ($n, $v) = each %$expected) {
100 104 100 100     806 if (defined($v) && !ref($v) && $v eq 'HT_DISABLED') {
      100        
101 1         3 push @disabled, $n;
102 1         4 next;
103             }
104 103         899 my $wc = $e_class->ht_find_widget($n);
105 103 100       1328 $res->{$n} = $wc ?
106             $wc->__ht_tester->bless_from_tree($wc, $v, $err)
107             : $class->bless_unknown_widget($n, $v, $err);
108             }
109 104         262 my $e_root = bless($res, $e_class);
110 104         261 $e_root->ht_set_widget_option($_, "is_disabled", 1) for @disabled;
111 104         252 $e_root->{"__HT_REVERTED__$_"} = 1 for @reverted;
112 104         513 $e_root->{"__HT_SEALED__$_"} = 1 for @sealed;
113 104         227 $e_root->{"__HT_UNSORTED__$_"} = 1 for @unsorted;
114 104         1378 return $e_root;
115             }
116              
117             sub do_comparison {
118 71     71 0 211 my ($class, $compare, $obj_class, $stash, $expected) = @_;
119 71         137 my $e_stash = {};
120 71         131 my @res;
121 71         618 my $e_root = $class->bless_from_tree_for_test($obj_class
122             , $expected, \@res);
123 70         584 $e_root->_ht_render_i($e_stash);
124              
125 69         430 push @res, $class->$compare($e_root, $stash, $e_stash);
126 69         3720 return @res;
127             }
128              
129 52     52 0 31311 sub check_stash { return shift()->do_comparison('compare_stashes', @_); }
130             sub check_text {
131 19     19 0 5283 return shift()->do_comparison('compare_text_to_stash', @_);
132             }
133              
134             =head2 Register_Widget_Tester($widget_class, $tester_class)
135              
136             Registers C<$tester_class> as tester for C<$widget_class>.
137              
138             =cut
139             sub Register_Widget_Tester {
140 69     69 1 216 my ($w_class, $t_class) = @_;
141 17     17   126 no strict 'refs';
  17         80  
  17         6416  
142 69     226   412 *{ "$w_class\::__ht_tester" } = sub { return $t_class; };
  69         2225  
  226         1311  
143             }
144              
145             sub _tree_to_param_fallback {
146 0     0   0 my ($class, $n) = @_;
147 0         0 confess "Unable to find widget for $n";
148             }
149              
150             sub convert_tree_to_param {
151 15     15 0 1387 my ($class, $obj_class, $r, $tree, $parent_name) = @_;
152 15         81 while (my ($n, $v) = each %$tree) {
153 19         142 my $sealit = ($n =~ s/^HT_SEALED_//);
154 19         107 my $wc = $obj_class->ht_find_widget($n);
155 19 50       272 if ($wc) {
156 19 100       63 $v = $wc->__ht_tester->convert_to_sealed($v) if $sealit;
157 19 100       546 $wc->__ht_tester->convert_to_param($wc, $r,
158             $parent_name ? $parent_name . "__$n" : $n, $v);
159             } else {
160 0           $class->_tree_to_param_fallback($n);
161             }
162             }
163             }
164              
165             my %_testers = qw(HTML::Tested::Value HTML::Tested::Test::Value
166             HTML::Tested::Value::Upload HTML::Tested::Test::Upload
167             HTML::Tested::Value::Radio HTML::Tested::Test::Radio
168             HTML::Tested::List HTML::Tested::Test::List);
169             while (my ($n, $v) = each %_testers) {
170 17     17   13004 eval "use $n; use $v;";
  17     17   62  
  17     17   706  
  17     17   26546  
  17     17   91  
  17     17   980  
  17     17   11594  
  17     17   56  
  17         590  
  17         19108  
  17         57  
  17         408  
  17         10921  
  17         49  
  17         2234  
  17         13527  
  17         130  
  17         413  
  17         10840  
  17         44  
  17         466  
  17         9802  
  17         119  
  17         397  
171             die "Unable to use $n or use $v" if $@;
172             Register_Widget_Tester($n, $v);
173             }
174              
175             1;