File Coverage

blib/lib/Test/XMLElement.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Test::XMLElement;
2 16     16   341977 use strict;
  16         39  
  16         633  
3 16     16   137 use warnings;
  16         28  
  16         727  
4              
5             our $VERSION = '0.04';
6              
7 16     16   82 use Test::Builder;
  16         38  
  16         341  
8 16     16   27867 use XML::Twig;
  0            
  0            
9             use XML::XPath;
10             use XML::Twig::XPath;
11              
12             my $Tst = Test::Builder->new();
13             my $XML;
14             my $LAST = '';
15              
16             ## Import subroutine is inspired by Test::Pod import method
17              
18             sub import {
19             my $self = shift;
20             my $caller = caller;
21             no strict 'refs';
22             *{$caller.'::have_child'} = \&have_child;
23             *{$caller.'::have_child_name'} = \&have_child_name;
24             *{$caller.'::child_count_is'} = \&child_count_is;
25             *{$caller.'::is_empty'} = \&is_empty;
26             *{$caller.'::has_attributes'} = \&has_attributes;
27             *{$caller.'::has_no_attrib'} = \&has_no_attrib;
28             *{$caller.'::number_of_attribs'} = \&number_of_attribs;
29             *{$caller.'::attrib_value'} = \&attrib_value;
30             *{$caller.'::attrib_name'} = \&attrib_name;
31             *{$caller.'::nth_child_name'} = \&nth_child_name;
32             *{$caller.'::all_children_are'} = \&all_children_are;
33             *{$caller.'::child_has_cdata'} = \&child_has_cdata;
34             *{$caller.'::is_descendants'} = \&is_descendants;
35             *{$caller.'::is_xpath'} = \&is_xpath;
36             *{$caller.'::is_xpath_count'} = \&is_xpath_count;
37            
38             $Tst->exported_to($caller);
39             $Tst->plan(@_);
40             }
41              
42              
43              
44             sub have_child {
45             my ($elt, $msg) = @_;
46             my $valid_elt = _parse($elt,$msg);
47             return 0 unless $valid_elt;
48             return
49             (
50             $Tst->ok(scalar(_child_elements($valid_elt)),$msg) ||
51             $Tst->diag("Element ",$valid_elt->name," do not have any children")
52             );
53             }
54              
55             sub have_child_name {
56             my ($elt, $name, $msg) = @_;
57             my $valid_elt = _parse($elt,$msg);
58             return 0 unless $valid_elt;
59             my @child = _child_elements($valid_elt);
60             return
61             (
62             $Tst->ok(scalar(@child),$msg) ||
63             $Tst->diag("Element ",$valid_elt->name," do not have any children")
64             ) unless (@child);
65             return
66             (
67             $Tst->ok(scalar(grep {$_->name eq $name} @child), $msg) ||
68             $Tst->diag("Element \'",$valid_elt->name,"\' do not have any child named $name")
69             );
70             }
71              
72             sub nth_child_name {
73             my ($elt, $n, $name, $msg) = @_;
74             my $valid_elt = _parse($elt,$msg);
75             return 0 unless $valid_elt;
76             my @child = _child_elements($valid_elt);
77             return
78             (
79             $Tst->ok(scalar(@child),$msg) ||
80             $Tst->diag("Element ",$valid_elt->name," do not have any children")
81             ) unless (@child);
82             return
83             (
84             $Tst->is_eq( $child[$n - 1]->name,$name, $msg) ||
85             $Tst->diag("Element \'",$valid_elt->name,"\' do not have ",$n - 1," child named $name")
86             );
87             }
88              
89             sub all_children_are {
90             my ($elt, $name, $msg) = @_;
91             my $valid_elt = _parse($elt,$msg);
92             return 0 unless $valid_elt;
93             my @child = _child_elements($valid_elt);
94             return
95             (
96             $Tst->ok(scalar(@child),$msg) ||
97             $Tst->diag("Element ",$valid_elt->name," do not have any children")
98             ) unless (@child);
99             return
100             (
101             $Tst->is_num( scalar (grep {$_->name eq $name} @child), scalar @child, $msg) ||
102             $Tst->diag("Element \'",$valid_elt->name,"\' do not have all child named $name")
103             );
104             }
105              
106              
107             sub child_count_is {
108             my ($elt, $num, $msg) = @_;
109             my $valid_elt = _parse($elt,$msg);
110             return 0 unless $valid_elt;
111             my @child = _child_elements($valid_elt);
112             return
113             (
114             $Tst->is_num(scalar(@child), $num, $msg) ||
115             $Tst->diag("Element \'",$valid_elt->name,"\' do not have $num children")
116             );
117             }
118              
119             sub is_empty {
120             my ($elt, $msg) = @_;
121             my $valid_elt = _parse($elt,$msg);
122             return 0 unless $valid_elt;
123             return
124             (
125             $Tst->ok($valid_elt->is_empty, $msg) ||
126             $Tst->diag("Element ",$valid_elt->name," is not empty")
127             );
128             }
129              
130             sub has_attributes {
131             my ($elt, $msg) = @_;
132             my $valid_elt = _parse($elt,$msg);
133             return 0 unless $valid_elt;
134             return
135             (
136             $Tst->ok($valid_elt->has_atts, $msg) ||
137             $Tst->diag("Element ",$valid_elt->name," dont have attributes")
138             );
139             }
140              
141             sub has_no_attrib {
142             my ($elt, $msg) = @_;
143             my $valid_elt = _parse($elt,$msg);
144             return 0 unless $valid_elt;
145             return
146             (
147             $Tst->ok($valid_elt->has_no_atts, $msg) ||
148             $Tst->diag("Element ",$valid_elt->name," have attributes")
149             );
150             }
151              
152             sub number_of_attribs {
153             my ($elt, $num, $msg) = @_;
154             my $valid_elt = _parse($elt,$msg);
155             return 0 unless $valid_elt;
156             return
157             (
158             $Tst->is_num($valid_elt->att_nb, $num, $msg) ||
159             $Tst->diag("Element ",$valid_elt->name," have ",$valid_elt->att_nb," attributes")
160             );
161             }
162              
163             sub attrib_name {
164             my ($elt, $name, $msg) = @_;
165             my $valid_elt = _parse($elt,$msg);
166             return 0 unless $valid_elt;
167             my @atts = $valid_elt->att_names;
168             return
169             (
170             $Tst->ok(scalar(@atts),$msg) ||
171             $Tst->diag("Element ",$valid_elt->name," do not have any attributes")
172             ) unless (@atts);
173             return
174             (
175             $Tst->ok(scalar(grep {$_ eq $name} @atts), $msg) ||
176             $Tst->diag("Element \'",$valid_elt->name,"\' do not have any attribute named $name")
177             );
178             }
179              
180              
181             sub attrib_value {
182             my ($elt, $name, $value, $msg) = @_;
183             my $valid_elt = _parse($elt,$msg);
184             return 0 unless $valid_elt;
185             my @atts = $valid_elt->att_names;
186             return
187             (
188             $Tst->ok(scalar(@atts),$msg) ||
189             $Tst->diag("Element ",$valid_elt->name," do not have any attributes")
190             ) unless (@atts);
191             return
192             (
193             $Tst->is_eq($valid_elt->att($name), $value, $msg) ||
194             $Tst->diag("Element \'",$valid_elt->name,"\' do not have any attribute named $name")
195             );
196             }
197              
198             sub child_has_cdata {
199             my ($elt, $msg) = @_;
200             my $valid_elt = _parse($elt,$msg);
201             return 0 unless $valid_elt;
202             my @cdata = grep {$_->is_cdata} $valid_elt->children;
203             return
204             (
205             $Tst->ok(scalar(@cdata),$msg) ||
206             $Tst->diag("Element ",$valid_elt->name," do not have any CDATA")
207             )
208             }
209              
210             sub is_descendants {
211             my ($elt, $name, $msg) = @_;
212             my $valid_elt = _parse($elt,$msg);
213             return 0 unless $valid_elt;
214             return
215             (
216             $Tst->ok(scalar($valid_elt->descendants($name)),$msg) ||
217             $Tst->diag("Element ",$valid_elt->name," do not have any descendants for $name")
218             );
219             }
220              
221             sub is_xpath {
222             my ($elt, $xpath, $msg) = @_;
223             my $valid_elt = _parse($elt,$msg,"xpath");
224             my @xp_cnt;
225             return 0 unless $valid_elt;
226             eval {
227             @xp_cnt = $valid_elt->findnodes($xpath,$valid_elt->root);
228             };
229             return
230             (
231             $Tst->ok(0,$msg) ||
232             $Tst->diag("Failed due to $@")
233             ) if $@;
234              
235             return
236             (
237             $Tst->ok(scalar(@xp_cnt),$msg) ||
238             $Tst->diag("Element ",$valid_elt->root->name," do not have elements matching $xpath")
239             );
240             }
241              
242             sub is_xpath_count {
243             my ($elt, $xpath, $count, $msg) = @_;
244             my $valid_elt = _parse($elt,$msg,"xpath");
245             my @xp_cnt;
246             return 0 unless $valid_elt;
247             eval {
248             @xp_cnt = $valid_elt->findnodes($xpath,$valid_elt->root);
249             };
250             return
251             (
252             $Tst->ok(0,$msg) ||
253             $Tst->diag("Failed due to $@")
254             ) if $@;
255              
256             return
257             (
258             $Tst->is_num(scalar(@xp_cnt),$count,$msg) ||
259             $Tst->diag("XPath expression $xpath did not had same elements as required count $count")
260             );
261             }
262              
263             ### Private Subroutines ##
264              
265             sub _parse {
266             local $Test::Builder::Level += 2;
267             my $string = shift or return $Tst->diag("XML String is not defined");
268             my $msg = shift;
269             my $xp = shift;
270             return $XML if ($string eq $LAST);
271             if (not $xp) {
272             eval {
273             $XML = parse XML::Twig::Elt($string);
274             };
275             }
276             else {
277             eval {
278             $XML = parse XML::Twig::XPath($string);
279             };
280             }
281             $@ ? ($Tst->ok(0,$msg)||$Tst->diag($@)) : $XML;
282             }
283              
284             sub _child_elements {
285             my ($elt) = shift;
286             return grep {$_->is_elt} $elt->children;
287             }
288              
289             1;
290             __END__