Commit | Line | Data |
456a815d |
1 | use strict; |
2 | use warnings FATAL => 'all'; |
3 | use Test::More; |
4 | |
5 | use HTML::Zoom::Parser::BuiltIn; |
6 | use HTML::Zoom::Producer::BuiltIn; |
7 | use HTML::Zoom::SelectorParser; |
8 | use HTML::Zoom::FilterBuilder; |
9 | use HTML::Zoom::FilterStream; |
10 | |
11 | my $tmpl = <<END; |
12 | <body> |
13 | <div class="main"> |
14 | <span class="hilight name">Bob</span> |
15 | <span class="career">Builder</span> |
16 | <hr /> |
17 | </div> |
18 | </body> |
19 | END |
20 | |
d80786d0 |
21 | sub src_stream { HTML::Zoom::Parser::BuiltIn->new->html_to_stream($tmpl); } |
456a815d |
22 | |
d80786d0 |
23 | sub html_sink { HTML::Zoom::Producer::BuiltIn->new->html_from_stream($_[0]) } |
456a815d |
24 | |
25 | my $fb = HTML::Zoom::FilterBuilder->new; |
26 | |
27 | my $sp = HTML::Zoom::SelectorParser->new; |
28 | |
29 | sub filter { |
30 | my ($stream, $sel, $cb) = @_; |
31 | return HTML::Zoom::FilterStream->new({ |
32 | stream => $stream, |
33 | match => $sp->parse_selector($sel), |
34 | filter => do { local $_ = $fb; $cb->($fb) } |
35 | }); |
36 | } |
37 | |
38 | sub run_for (&;$) { |
39 | my $cb = shift; |
40 | (html_sink |
41 | (filter |
42 | src_stream, |
43 | (shift or '.main'), |
44 | $cb |
45 | ) |
46 | ) |
47 | } |
48 | |
8f962884 |
49 | my ($expect, @ev); |
50 | |
51 | ($expect = $tmpl) =~ s/class="main"/class="foo"/; |
52 | |
53 | is( |
54 | run_for { $_->set_attribute({ name => 'class', value => 'foo' }) }, |
55 | $expect, |
56 | 'set attribute on existing attribute' |
57 | ); |
58 | |
59 | ($expect = $tmpl) =~ s/class="main"/class="main" foo="bar"/; |
60 | |
61 | is( |
62 | run_for { $_->set_attribute({ name => 'foo', value => 'bar' }) }, |
63 | $expect, |
64 | 'set attribute on non existing attribute' |
65 | ); |
66 | |
67 | ($expect = $tmpl) =~ s/class="main"/class="main foo"/; |
68 | |
69 | is( |
2daa653a |
70 | run_for { $_->add_to_attribute({ name => 'class', value => 'foo' }) }, |
8f962884 |
71 | $expect, |
72 | 'add attribute on existing attribute' |
73 | ); |
74 | |
75 | ($expect = $tmpl) =~ s/class="main"/class="main" foo="bar"/; |
76 | |
77 | is( |
2daa653a |
78 | run_for { $_->add_to_attribute({ name => 'foo', value => 'bar' }) }, |
8f962884 |
79 | $expect, |
80 | 'add attribute on non existing attribute' |
81 | ); |
82 | |
83 | ($expect = $tmpl) =~ s/ class="main"//; |
84 | |
85 | is( |
86 | run_for { $_->remove_attribute({ name => 'class' }) }, |
87 | $expect, |
88 | 'remove attribute on existing attribute' |
89 | ); |
90 | |
91 | is( |
92 | run_for { $_->remove_attribute({ name => 'foo' }) }, |
93 | $tmpl, |
94 | 'remove attribute on non existing attribute' |
95 | ); |
96 | |
97 | ($expect = $tmpl) =~ s/(?=<div)/O HAI/; |
456a815d |
98 | |
99 | my $ohai = [ { type => 'TEXT', raw => 'O HAI' } ]; |
100 | |
101 | is( |
102 | run_for { $_->add_before($ohai) }, |
103 | $expect, |
104 | 'add_before ok' |
105 | ); |
106 | |
107 | ($expect = $tmpl) =~ s/(?<=<\/div>)/O HAI/; |
108 | |
109 | is( |
110 | run_for { $_->add_after($ohai) }, |
111 | $expect, |
112 | 'add_after ok' |
113 | ); |
114 | |
115 | ($expect = $tmpl) =~ s/(?<=class="main">)/O HAI/; |
116 | |
117 | is( |
865bb5d2 |
118 | run_for { $_->prepend_content($ohai) }, |
456a815d |
119 | $expect, |
865bb5d2 |
120 | 'prepend_content ok' |
456a815d |
121 | ); |
122 | |
123 | ($expect = $tmpl) =~ s/<hr \/>/<hr>O HAI<\/hr>/; |
124 | |
125 | is( |
865bb5d2 |
126 | (run_for { $_->prepend_content($ohai) } 'hr'), |
456a815d |
127 | $expect, |
865bb5d2 |
128 | 'prepend_content ok with in place close' |
456a815d |
129 | ); |
130 | |
131 | is( |
132 | run_for { $_->replace($ohai) }, |
133 | '<body> |
134 | O HAI |
135 | </body> |
136 | ', |
137 | 'replace ok' |
138 | ); |
139 | |
8f962884 |
140 | @ev = (); |
c86c0ce2 |
141 | |
142 | is( |
143 | run_for { $_->collect({ into => \@ev }) }, |
144 | '<body> |
145 | |
146 | </body> |
147 | ', |
148 | 'collect removes without passthrough' |
149 | ); |
150 | |
151 | is( |
152 | HTML::Zoom::Producer::BuiltIn->html_from_events(\@ev), |
153 | '<div class="main"> |
154 | <span class="hilight name">Bob</span> |
155 | <span class="career">Builder</span> |
156 | <hr /> |
157 | </div>', |
158 | 'collect collected right events' |
159 | ); |
41153e87 |
160 | |
8f962884 |
161 | @ev = (); |
41153e87 |
162 | |
163 | is( |
865bb5d2 |
164 | run_for { $_->collect({ into => \@ev, content => 1 }) }, |
8f962884 |
165 | '<body> |
166 | <div class="main"></div> |
167 | </body> |
168 | ', |
865bb5d2 |
169 | 'collect w/content removes correctly' |
41153e87 |
170 | ); |
171 | |
172 | is( |
8f962884 |
173 | HTML::Zoom::Producer::BuiltIn->html_from_events(\@ev), |
174 | ' |
175 | <span class="hilight name">Bob</span> |
176 | <span class="career">Builder</span> |
177 | <hr /> |
178 | ', |
865bb5d2 |
179 | 'collect w/content collects correctly' |
41153e87 |
180 | ); |
181 | |
11cc25dd |
182 | is( |
865bb5d2 |
183 | run_for { $_->replace($ohai, { content => 1 }) }, |
11cc25dd |
184 | '<body> |
185 | <div class="main">O HAI</div> |
186 | </body> |
187 | ', |
865bb5d2 |
188 | 'replace w/content' |
11cc25dd |
189 | ); |
190 | |
a25b8d4d |
191 | ($expect = $tmpl) =~ s/(?=<\/div>)/O HAI/; |
192 | |
193 | is( |
865bb5d2 |
194 | run_for { $_->append_content($ohai) }, |
a25b8d4d |
195 | $expect, |
865bb5d2 |
196 | 'append content ok' |
a25b8d4d |
197 | ); |
198 | |
865bb5d2 |
199 | my $r_content = sub { my $r = shift; sub { $_->replace($r, { content => 1 }) } }; |
3cdbc13f |
200 | |
201 | is( |
202 | run_for { |
203 | $_->repeat( |
204 | [ |
205 | sub { |
206 | filter |
865bb5d2 |
207 | filter($_ => '.name' => $r_content->('mst')) |
208 | => '.career' => $r_content->('Chainsaw Wielder') |
3cdbc13f |
209 | }, |
210 | sub { |
211 | filter |
865bb5d2 |
212 | filter($_ => '.name' => $r_content->('mdk')) |
213 | => '.career' => $r_content->('Adminion') |
3cdbc13f |
214 | }, |
215 | ] |
216 | ) |
217 | }, |
218 | q{<body> |
219 | <div class="main"> |
220 | <span class="hilight name">mst</span> |
221 | <span class="career">Chainsaw Wielder</span> |
222 | <hr /> |
223 | </div><div class="main"> |
224 | <span class="hilight name">mdk</span> |
225 | <span class="career">Adminion</span> |
226 | <hr /> |
227 | </div> |
228 | </body> |
229 | }, |
230 | 'repeat ok' |
231 | ); |
232 | |
865bb5d2 |
233 | is( |
234 | run_for { |
235 | $_->repeat_content( |
236 | [ |
237 | sub { |
238 | filter |
239 | filter($_ => '.name' => $r_content->('mst')) |
240 | => '.career' => $r_content->('Chainsaw Wielder') |
241 | }, |
242 | sub { |
243 | filter |
244 | filter($_ => '.name' => $r_content->('mdk')) |
245 | => '.career' => $r_content->('Adminion') |
246 | }, |
247 | ] |
248 | ) |
249 | }, |
250 | q{<body> |
251 | <div class="main"> |
252 | <span class="hilight name">mst</span> |
253 | <span class="career">Chainsaw Wielder</span> |
254 | <hr /> |
255 | |
256 | <span class="hilight name">mdk</span> |
257 | <span class="career">Adminion</span> |
258 | <hr /> |
259 | </div> |
260 | </body> |
261 | }, |
262 | 'repeat_content ok' |
263 | ); |
3cdbc13f |
264 | |
dae33531 |
265 | is( |
266 | run_for { |
267 | my @between; |
268 | $_->repeat_content( |
269 | [ |
270 | sub { |
b5a48c47 |
271 | HTML::Zoom::ArrayStream->new({ array => [ |
dae33531 |
272 | (filter |
273 | filter($_ => '.name' => $r_content->('mst')) |
274 | => '.career' => $r_content->('Chainsaw Wielder')), |
b5a48c47 |
275 | HTML::Zoom::ArrayStream->new({ array => \@between }) |
276 | ] })->flatten |
dae33531 |
277 | }, |
278 | sub { |
279 | filter |
280 | filter($_ => '.name' => $r_content->('mdk')) |
281 | => '.career' => $r_content->('Adminion') |
282 | }, |
283 | ], |
284 | { filter => sub { |
285 | filter $_[0] => 'hr' => sub { $_->collect({ into => \@between }) } |
286 | } |
287 | } |
288 | ) |
289 | }, |
290 | q{<body> |
291 | <div class="main"> |
292 | <span class="hilight name">mst</span> |
293 | <span class="career">Chainsaw Wielder</span> |
294 | <hr /> |
295 | <span class="hilight name">mdk</span> |
296 | <span class="career">Adminion</span> |
297 | |
298 | </div> |
299 | </body> |
300 | }, |
301 | 'repeat_content with filter ok' |
302 | ); |
303 | |
f8ed299b |
304 | is( |
305 | run_for { |
306 | my @between; |
307 | $_->repeat_content( |
308 | [ |
309 | sub { |
310 | filter |
311 | filter($_ => '.name' => $r_content->('mst')) |
312 | => '.career' => $r_content->('Chainsaw Wielder') |
313 | }, |
314 | sub { |
315 | filter |
316 | filter($_ => '.name' => $r_content->('mdk')) |
317 | => '.career' => $r_content->('Adminion') |
318 | }, |
319 | ], |
320 | { repeat_between => 'hr' } |
321 | ) |
322 | }, |
323 | q{<body> |
324 | <div class="main"> |
325 | <span class="hilight name">mst</span> |
326 | <span class="career">Chainsaw Wielder</span> |
327 | <hr /> |
328 | <span class="hilight name">mdk</span> |
329 | <span class="career">Adminion</span> |
330 | |
331 | </div> |
332 | </body> |
333 | }, |
334 | 'repeat_content using repeat_between ok' |
335 | ); |
336 | |
456a815d |
337 | done_testing; |