- Add a failing test for meta chars in selectors
[catagits/HTML-Zoom.git] / t / selectors.t
1 use strictures 1;
2 use Test::More;
3
4 use HTML::Zoom;
5
6 my $tmpl = <<END;
7 <body>
8   <div class="main">
9     <span prop='moo' class="hilight name">Bob</span>
10     <span class="career">Builder</span>
11     <hr />
12   </div>
13 </body>
14 END
15
16 my $stub = '<div class="waargh"></div>';
17
18 # el#id
19 is( HTML::Zoom->from_html('<div id="yo"></div>'.$stub)
20    ->select('div#yo')
21       ->replace_content('grg')
22    ->to_html,
23    '<div id="yo">grg</div>'.$stub,
24    'E#id works' );
25
26 # el.class1
27 is( HTML::Zoom->from_html('<div class="yo"></div>'.$stub)
28    ->select('div.yo')
29       ->replace_content('grg')
30    ->to_html,
31    '<div class="yo">grg</div>'.$stub,
32    'E.class works' );
33
34
35 # el.class\.1
36 is( HTML::Zoom->from_html('<div class="yo.yo"></div>'.$stub)
37    ->select('div.yo\.yo')
38       ->replace_content('grg')
39    ->to_html,
40    '<div class="yo.yo">grg</div>'.$stub,
41    'E.class\.0 works' );
42
43 # el[attr]
44 is( HTML::Zoom->from_html('<div frew="yo"></div>'.$stub)
45    ->select('div[frew]')
46       ->replace_content('grg')
47    ->to_html,
48    '<div frew="yo">grg</div>'.$stub,
49    'E[attr] works' );
50
51 # *[attr]
52 is( HTML::Zoom->from_html('<div frew="yo"></div><span frew="ay"></span>'.$stub)
53    ->select('*[frew]')
54       ->replace_content('grg')
55    ->to_html,
56    '<div frew="yo">grg</div><span frew="ay">grg</span>'.$stub,
57    '*[attr] works' );
58
59 # el[attr="foo"]
60 is( HTML::Zoom->from_html('<div frew="yo"></div>'.$stub)
61    ->select('div[frew="yo"]')
62       ->replace_content('grg')
63    ->to_html,
64    '<div frew="yo">grg</div>'.$stub,
65    'E[attr="val"] works' );
66
67 # el[attr=foo]
68 is( HTML::Zoom->from_html('<div frew="yo"></div>'.$stub)
69     ->select('div[frew=yo]')
70     ->replace_content('grg')
71     ->to_html,
72     '<div frew="yo">grg</div>'.$stub,
73     'E[attr=val] works' );
74
75 # el[attr=foo\.bar]
76 is( HTML::Zoom->from_html('<div frew="yo.yo"></div>'.$stub)
77     ->select('div[frew=yo\.yo]')
78     ->replace_content('grg')
79     ->to_html,
80     '<div frew="yo.yo">grg</div>'.$stub,
81     'E[attr=foo\.bar] works' );
82
83 # el[attr!="foo"]
84 is( HTML::Zoom->from_html('<div f="f"></div><div class="quux"></div>'.$stub)
85     ->select('div[class!="waargh"]')
86        ->replace_content('grg')
87     ->to_html,
88     '<div f="f">grg</div><div class="quux">grg</div>'.$stub,
89     'E[attr!="val"] works' );
90
91 # el[attr*="foo"]
92 is( HTML::Zoom->from_html('<div f="frew goog"></div>'.$stub)
93    ->select('div[f*="oo"]')
94       ->replace_content('grg')
95    ->to_html,
96    '<div f="frew goog">grg</div>'.$stub,
97    'E[attr*="val"] works' );
98
99 # el[attr^="foo"]
100 is( HTML::Zoom->from_html('<div f="foobar"></div>'.$stub)
101    ->select('div[f^="foo"]')
102       ->replace_content('grg')
103    ->to_html,
104    '<div f="foobar">grg</div>'.$stub,
105    'E[attr^="val"] works' );
106
107 # el[attr$="foo"]
108 is( HTML::Zoom->from_html('<div f="foobar"></div>'.$stub)
109    ->select('div[f$="bar"]')
110       ->replace_content('grg')
111    ->to_html,
112    '<div f="foobar">grg</div>'.$stub,
113    'E[attr$="val"] works' );
114
115 # el[attr*="foo"]
116 is( HTML::Zoom->from_html('<div f="foo bar"></div>'.$stub)
117    ->select('div[f*="bar"]')
118       ->replace_content('grg')
119    ->to_html,
120    '<div f="foo bar">grg</div>'.$stub,
121    'E[attr*="val"] works' );
122
123 # el[attr~="foo"]
124 is( HTML::Zoom->from_html('<div frew="foo bar baz"></div>'.$stub)
125    ->select('div[frew~="bar"]')
126       ->replace_content('grg')
127    ->to_html,
128    '<div frew="foo bar baz">grg</div>'.$stub,
129    'E[attr~="val"] works' );
130
131 # el[attr|="foo"]
132 is( HTML::Zoom->from_html('<div lang="pl"></div><div lang="english"></div>'.
133                           '<div lang="en"></div><div lang="en-US"></div>'.$stub)
134    ->select('div[lang|="en"]')
135       ->replace_content('grg')
136    ->to_html,
137    '<div lang="pl"></div><div lang="english"></div>'.
138    '<div lang="en">grg</div><div lang="en-US">grg</div>'.$stub,
139    'E[attr|="val"] works' );
140
141 # [attr=bar]
142 ok( check_select( '[prop=moo]'), '[attr=bar]' );
143
144 # el[attr=bar],[prop=foo]
145 is( check_select('span[class=career],[prop=moo]'), 2,
146     'Multiple selectors: el[attr=bar],[attr=foo]');
147
148
149 # selector parse error test:
150 eval{
151     HTML::Zoom->from_html('<span att="bar"></span>')
152       ->select('[att=bar')
153       ->replace_content('cats')
154           ->to_html;
155 };
156 like( $@, qr/Error parsing dispatch specification/,
157       'Malformed attribute selector ([att=bar) results in a helpful error' );
158
159
160 TODO: {
161 local $TODO = "descendant selectors doesn't work yet";
162 # sel1 sel2
163 is( eval { HTML::Zoom->from_html('<table><tr></tr><tr></tr></table>')
164    ->select('table tr')
165       ->replace_content('<td></td>')
166    ->to_html },
167    '<table><tr><td></td></tr><tr><td></td></tr></table>',
168    'sel1 sel2 works' );
169 diag($@) if $@;
170
171 # sel1 sel2 sel3
172 is( eval { HTML::Zoom->from_html('<table><tr><td></td></tr><tr><td></td></tr></table>')
173    ->select('table tr td')
174       ->replace_content('frew')
175    ->to_html },
176    '<table><tr><td>frew</td></tr><tr><td>frew</td></tr></table>',
177    'sel1 sel2 sel3 works' );
178 diag($@) if $@;
179 }
180
181 done_testing;
182
183
184 sub check_select {
185     # less crude?:
186     my $output = HTML::Zoom
187     ->from_html($tmpl)
188     ->select(shift)->replace("the monkey")->to_html;
189     my $count = 0;
190     while ( $output =~ /the monkey/g ){
191         $count++;
192     }
193     return $count;
194 }