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