test replace inside
[catagits/HTML-Zoom.git] / t / actions.t
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
21 sub src_stream { HTML::Zoom::Parser::BuiltIn->html_to_stream($tmpl); }
22
23 sub html_sink { HTML::Zoom::Producer::BuiltIn->html_from_stream($_[0]) }
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
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(
70   run_for { $_->add_attribute({ name => 'class', value => 'foo' }) },
71   $expect,
72   'add attribute on existing attribute'
73 );
74
75 ($expect = $tmpl) =~ s/class="main"/class="main" foo="bar"/;
76
77 is(
78   run_for { $_->add_attribute({ name => 'foo', value => 'bar' }) },
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/;
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(
118   run_for { $_->prepend_inside($ohai) },
119   $expect,
120   'prepend_inside ok'
121 );
122
123 ($expect = $tmpl) =~ s/<hr \/>/<hr>O HAI<\/hr>/;
124
125 is(
126   (run_for { $_->prepend_inside($ohai) } 'hr'),
127   $expect,
128   'prepend_inside ok with in place close'
129 );
130
131 is(
132   run_for { $_->replace($ohai) },
133 '<body>
134   O HAI
135 </body>
136 ',
137   'replace ok'
138 );
139
140 @ev = ();
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 );
160
161 @ev = ();
162
163 is(
164   run_for { $_->collect({ into => \@ev, inside => 1 }) },
165   '<body>
166   <div class="main"></div>
167 </body>
168 ',
169   'collect w/inside removes correctly'
170 );
171
172 is(
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   ',
179   'collect w/inside collects correctly'
180 );
181
182 is(
183   run_for { $_->replace($ohai, { inside => 1 }) },
184   '<body>
185   <div class="main">O HAI</div>
186 </body>
187 ',
188   'replace w/inside'
189 );
190
191 done_testing;