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; |