Mercurial > genshi > genshi-test
comparison genshi/filters/tests/html.py @ 902:09cc3627654c experimental-inline
Sync `experimental/inline` branch with [source:trunk@1126].
author | cmlenz |
---|---|
date | Fri, 23 Apr 2010 21:08:26 +0000 |
parents | 1837f39efd6f |
children |
comparison
equal
deleted
inserted
replaced
830:de82830f8816 | 902:09cc3627654c |
---|---|
1 # -*- coding: utf-8 -*- | 1 # -*- coding: utf-8 -*- |
2 # | 2 # |
3 # Copyright (C) 2006-2008 Edgewall Software | 3 # Copyright (C) 2006-2009 Edgewall Software |
4 # All rights reserved. | 4 # All rights reserved. |
5 # | 5 # |
6 # This software is licensed as described in the file COPYING, which | 6 # This software is licensed as described in the file COPYING, which |
7 # you should have received as part of this distribution. The terms | 7 # you should have received as part of this distribution. The terms |
8 # are also available at http://genshi.edgewall.org/wiki/License. | 8 # are also available at http://genshi.edgewall.org/wiki/License. |
24 html = HTML("""<form><p> | 24 html = HTML("""<form><p> |
25 <input type="text" name="foo" /> | 25 <input type="text" name="foo" /> |
26 </p></form>""") | HTMLFormFiller() | 26 </p></form>""") | HTMLFormFiller() |
27 self.assertEquals("""<form><p> | 27 self.assertEquals("""<form><p> |
28 <input type="text" name="foo"/> | 28 <input type="text" name="foo"/> |
29 </p></form>""", unicode(html)) | 29 </p></form>""", html.render()) |
30 | 30 |
31 def test_fill_input_text_single_value(self): | 31 def test_fill_input_text_single_value(self): |
32 html = HTML("""<form><p> | 32 html = HTML("""<form><p> |
33 <input type="text" name="foo" /> | 33 <input type="text" name="foo" /> |
34 </p></form>""") | HTMLFormFiller(data={'foo': 'bar'}) | 34 </p></form>""") | HTMLFormFiller(data={'foo': 'bar'}) |
35 self.assertEquals("""<form><p> | 35 self.assertEquals("""<form><p> |
36 <input type="text" name="foo" value="bar"/> | 36 <input type="text" name="foo" value="bar"/> |
37 </p></form>""", unicode(html)) | 37 </p></form>""", html.render()) |
38 | 38 |
39 def test_fill_input_text_multi_value(self): | 39 def test_fill_input_text_multi_value(self): |
40 html = HTML("""<form><p> | 40 html = HTML("""<form><p> |
41 <input type="text" name="foo" /> | 41 <input type="text" name="foo" /> |
42 </p></form>""") | HTMLFormFiller(data={'foo': ['bar']}) | 42 </p></form>""") | HTMLFormFiller(data={'foo': ['bar']}) |
43 self.assertEquals("""<form><p> | 43 self.assertEquals("""<form><p> |
44 <input type="text" name="foo" value="bar"/> | 44 <input type="text" name="foo" value="bar"/> |
45 </p></form>""", unicode(html)) | 45 </p></form>""", html.render()) |
46 | 46 |
47 def test_fill_input_hidden_no_value(self): | 47 def test_fill_input_hidden_no_value(self): |
48 html = HTML("""<form><p> | 48 html = HTML("""<form><p> |
49 <input type="hidden" name="foo" /> | 49 <input type="hidden" name="foo" /> |
50 </p></form>""") | HTMLFormFiller() | 50 </p></form>""") | HTMLFormFiller() |
51 self.assertEquals("""<form><p> | 51 self.assertEquals("""<form><p> |
52 <input type="hidden" name="foo"/> | 52 <input type="hidden" name="foo"/> |
53 </p></form>""", unicode(html)) | 53 </p></form>""", html.render()) |
54 | 54 |
55 def test_fill_input_hidden_single_value(self): | 55 def test_fill_input_hidden_single_value(self): |
56 html = HTML("""<form><p> | 56 html = HTML("""<form><p> |
57 <input type="hidden" name="foo" /> | 57 <input type="hidden" name="foo" /> |
58 </p></form>""") | HTMLFormFiller(data={'foo': 'bar'}) | 58 </p></form>""") | HTMLFormFiller(data={'foo': 'bar'}) |
59 self.assertEquals("""<form><p> | 59 self.assertEquals("""<form><p> |
60 <input type="hidden" name="foo" value="bar"/> | 60 <input type="hidden" name="foo" value="bar"/> |
61 </p></form>""", unicode(html)) | 61 </p></form>""", html.render()) |
62 | 62 |
63 def test_fill_input_hidden_multi_value(self): | 63 def test_fill_input_hidden_multi_value(self): |
64 html = HTML("""<form><p> | 64 html = HTML("""<form><p> |
65 <input type="hidden" name="foo" /> | 65 <input type="hidden" name="foo" /> |
66 </p></form>""") | HTMLFormFiller(data={'foo': ['bar']}) | 66 </p></form>""") | HTMLFormFiller(data={'foo': ['bar']}) |
67 self.assertEquals("""<form><p> | 67 self.assertEquals("""<form><p> |
68 <input type="hidden" name="foo" value="bar"/> | 68 <input type="hidden" name="foo" value="bar"/> |
69 </p></form>""", unicode(html)) | 69 </p></form>""", html.render()) |
70 | 70 |
71 def test_fill_textarea_no_value(self): | 71 def test_fill_textarea_no_value(self): |
72 html = HTML("""<form><p> | 72 html = HTML("""<form><p> |
73 <textarea name="foo"></textarea> | 73 <textarea name="foo"></textarea> |
74 </p></form>""") | HTMLFormFiller() | 74 </p></form>""") | HTMLFormFiller() |
75 self.assertEquals("""<form><p> | 75 self.assertEquals("""<form><p> |
76 <textarea name="foo"/> | 76 <textarea name="foo"/> |
77 </p></form>""", unicode(html)) | 77 </p></form>""", html.render()) |
78 | 78 |
79 def test_fill_textarea_single_value(self): | 79 def test_fill_textarea_single_value(self): |
80 html = HTML("""<form><p> | 80 html = HTML("""<form><p> |
81 <textarea name="foo"></textarea> | 81 <textarea name="foo"></textarea> |
82 </p></form>""") | HTMLFormFiller(data={'foo': 'bar'}) | 82 </p></form>""") | HTMLFormFiller(data={'foo': 'bar'}) |
83 self.assertEquals("""<form><p> | 83 self.assertEquals("""<form><p> |
84 <textarea name="foo">bar</textarea> | 84 <textarea name="foo">bar</textarea> |
85 </p></form>""", unicode(html)) | 85 </p></form>""", html.render()) |
86 | 86 |
87 def test_fill_textarea_multi_value(self): | 87 def test_fill_textarea_multi_value(self): |
88 html = HTML("""<form><p> | 88 html = HTML("""<form><p> |
89 <textarea name="foo"></textarea> | 89 <textarea name="foo"></textarea> |
90 </p></form>""") | HTMLFormFiller(data={'foo': ['bar']}) | 90 </p></form>""") | HTMLFormFiller(data={'foo': ['bar']}) |
91 self.assertEquals("""<form><p> | 91 self.assertEquals("""<form><p> |
92 <textarea name="foo">bar</textarea> | 92 <textarea name="foo">bar</textarea> |
93 </p></form>""", unicode(html)) | 93 </p></form>""", html.render()) |
94 | 94 |
95 def test_fill_input_checkbox_no_value(self): | 95 def test_fill_input_checkbox_no_value(self): |
96 html = HTML("""<form><p> | 96 html = HTML("""<form><p> |
97 <input type="checkbox" name="foo" /> | 97 <input type="checkbox" name="foo" /> |
98 </p></form>""") | HTMLFormFiller() | 98 </p></form>""") | HTMLFormFiller() |
99 self.assertEquals("""<form><p> | 99 self.assertEquals("""<form><p> |
100 <input type="checkbox" name="foo"/> | 100 <input type="checkbox" name="foo"/> |
101 </p></form>""", unicode(html)) | 101 </p></form>""", html.render()) |
102 | 102 |
103 def test_fill_input_checkbox_single_value_auto(self): | 103 def test_fill_input_checkbox_single_value_auto(self): |
104 html = HTML("""<form><p> | 104 html = HTML("""<form><p> |
105 <input type="checkbox" name="foo" /> | 105 <input type="checkbox" name="foo" /> |
106 </p></form>""") | 106 </p></form>""") |
107 self.assertEquals("""<form><p> | 107 self.assertEquals("""<form><p> |
108 <input type="checkbox" name="foo"/> | 108 <input type="checkbox" name="foo"/> |
109 </p></form>""", unicode(html | HTMLFormFiller(data={'foo': ''}))) | 109 </p></form>""", (html | HTMLFormFiller(data={'foo': ''})).render()) |
110 self.assertEquals("""<form><p> | 110 self.assertEquals("""<form><p> |
111 <input type="checkbox" name="foo" checked="checked"/> | 111 <input type="checkbox" name="foo" checked="checked"/> |
112 </p></form>""", unicode(html | HTMLFormFiller(data={'foo': 'on'}))) | 112 </p></form>""", (html | HTMLFormFiller(data={'foo': 'on'})).render()) |
113 | 113 |
114 def test_fill_input_checkbox_single_value_defined(self): | 114 def test_fill_input_checkbox_single_value_defined(self): |
115 html = HTML("""<form><p> | 115 html = HTML("""<form><p> |
116 <input type="checkbox" name="foo" value="1" /> | 116 <input type="checkbox" name="foo" value="1" /> |
117 </p></form>""") | 117 </p></form>""") |
118 self.assertEquals("""<form><p> | 118 self.assertEquals("""<form><p> |
119 <input type="checkbox" name="foo" value="1" checked="checked"/> | 119 <input type="checkbox" name="foo" value="1" checked="checked"/> |
120 </p></form>""", unicode(html | HTMLFormFiller(data={'foo': '1'}))) | 120 </p></form>""", (html | HTMLFormFiller(data={'foo': '1'})).render()) |
121 self.assertEquals("""<form><p> | 121 self.assertEquals("""<form><p> |
122 <input type="checkbox" name="foo" value="1"/> | 122 <input type="checkbox" name="foo" value="1"/> |
123 </p></form>""", unicode(html | HTMLFormFiller(data={'foo': '2'}))) | 123 </p></form>""", (html | HTMLFormFiller(data={'foo': '2'})).render()) |
124 | 124 |
125 def test_fill_input_checkbox_multi_value_auto(self): | 125 def test_fill_input_checkbox_multi_value_auto(self): |
126 html = HTML("""<form><p> | 126 html = HTML("""<form><p> |
127 <input type="checkbox" name="foo" /> | 127 <input type="checkbox" name="foo" /> |
128 </p></form>""") | 128 </p></form>""") |
129 self.assertEquals("""<form><p> | 129 self.assertEquals("""<form><p> |
130 <input type="checkbox" name="foo"/> | 130 <input type="checkbox" name="foo"/> |
131 </p></form>""", unicode(html | HTMLFormFiller(data={'foo': []}))) | 131 </p></form>""", (html | HTMLFormFiller(data={'foo': []})).render()) |
132 self.assertEquals("""<form><p> | 132 self.assertEquals("""<form><p> |
133 <input type="checkbox" name="foo" checked="checked"/> | 133 <input type="checkbox" name="foo" checked="checked"/> |
134 </p></form>""", unicode(html | HTMLFormFiller(data={'foo': ['on']}))) | 134 </p></form>""", (html | HTMLFormFiller(data={'foo': ['on']})).render()) |
135 | 135 |
136 def test_fill_input_checkbox_multi_value_defined(self): | 136 def test_fill_input_checkbox_multi_value_defined(self): |
137 html = HTML("""<form><p> | 137 html = HTML("""<form><p> |
138 <input type="checkbox" name="foo" value="1" /> | 138 <input type="checkbox" name="foo" value="1" /> |
139 </p></form>""") | 139 </p></form>""") |
140 self.assertEquals("""<form><p> | 140 self.assertEquals("""<form><p> |
141 <input type="checkbox" name="foo" value="1" checked="checked"/> | 141 <input type="checkbox" name="foo" value="1" checked="checked"/> |
142 </p></form>""", unicode(html | HTMLFormFiller(data={'foo': ['1']}))) | 142 </p></form>""", (html | HTMLFormFiller(data={'foo': ['1']})).render()) |
143 self.assertEquals("""<form><p> | 143 self.assertEquals("""<form><p> |
144 <input type="checkbox" name="foo" value="1"/> | 144 <input type="checkbox" name="foo" value="1"/> |
145 </p></form>""", unicode(html | HTMLFormFiller(data={'foo': ['2']}))) | 145 </p></form>""", (html | HTMLFormFiller(data={'foo': ['2']})).render()) |
146 | 146 |
147 def test_fill_input_radio_no_value(self): | 147 def test_fill_input_radio_no_value(self): |
148 html = HTML("""<form><p> | 148 html = HTML("""<form><p> |
149 <input type="radio" name="foo" /> | 149 <input type="radio" name="foo" /> |
150 </p></form>""") | HTMLFormFiller() | 150 </p></form>""") | HTMLFormFiller() |
151 self.assertEquals("""<form><p> | 151 self.assertEquals("""<form><p> |
152 <input type="radio" name="foo"/> | 152 <input type="radio" name="foo"/> |
153 </p></form>""", unicode(html)) | 153 </p></form>""", html.render()) |
154 | 154 |
155 def test_fill_input_radio_single_value(self): | 155 def test_fill_input_radio_single_value(self): |
156 html = HTML("""<form><p> | 156 html = HTML("""<form><p> |
157 <input type="radio" name="foo" value="1" /> | 157 <input type="radio" name="foo" value="1" /> |
158 </p></form>""") | 158 </p></form>""") |
159 self.assertEquals("""<form><p> | 159 self.assertEquals("""<form><p> |
160 <input type="radio" name="foo" value="1" checked="checked"/> | 160 <input type="radio" name="foo" value="1" checked="checked"/> |
161 </p></form>""", unicode(html | HTMLFormFiller(data={'foo': '1'}))) | 161 </p></form>""", (html | HTMLFormFiller(data={'foo': '1'})).render()) |
162 self.assertEquals("""<form><p> | 162 self.assertEquals("""<form><p> |
163 <input type="radio" name="foo" value="1"/> | 163 <input type="radio" name="foo" value="1"/> |
164 </p></form>""", unicode(html | HTMLFormFiller(data={'foo': '2'}))) | 164 </p></form>""", (html | HTMLFormFiller(data={'foo': '2'})).render()) |
165 | 165 |
166 def test_fill_input_radio_multi_value(self): | 166 def test_fill_input_radio_multi_value(self): |
167 html = HTML("""<form><p> | 167 html = HTML("""<form><p> |
168 <input type="radio" name="foo" value="1" /> | 168 <input type="radio" name="foo" value="1" /> |
169 </p></form>""") | 169 </p></form>""") |
170 self.assertEquals("""<form><p> | 170 self.assertEquals("""<form><p> |
171 <input type="radio" name="foo" value="1" checked="checked"/> | 171 <input type="radio" name="foo" value="1" checked="checked"/> |
172 </p></form>""", unicode(html | HTMLFormFiller(data={'foo': ['1']}))) | 172 </p></form>""", (html | HTMLFormFiller(data={'foo': ['1']})).render()) |
173 self.assertEquals("""<form><p> | 173 self.assertEquals("""<form><p> |
174 <input type="radio" name="foo" value="1"/> | 174 <input type="radio" name="foo" value="1"/> |
175 </p></form>""", unicode(html | HTMLFormFiller(data={'foo': ['2']}))) | 175 </p></form>""", (html | HTMLFormFiller(data={'foo': ['2']})).render()) |
176 | 176 |
177 def test_fill_select_no_value_auto(self): | 177 def test_fill_select_no_value_auto(self): |
178 html = HTML("""<form><p> | 178 html = HTML("""<form><p> |
179 <select name="foo"> | 179 <select name="foo"> |
180 <option>1</option> | 180 <option>1</option> |
186 <select name="foo"> | 186 <select name="foo"> |
187 <option>1</option> | 187 <option>1</option> |
188 <option>2</option> | 188 <option>2</option> |
189 <option>3</option> | 189 <option>3</option> |
190 </select> | 190 </select> |
191 </p></form>""", unicode(html)) | 191 </p></form>""", html.render()) |
192 | 192 |
193 def test_fill_select_no_value_defined(self): | 193 def test_fill_select_no_value_defined(self): |
194 html = HTML("""<form><p> | 194 html = HTML("""<form><p> |
195 <select name="foo"> | 195 <select name="foo"> |
196 <option value="1">1</option> | 196 <option value="1">1</option> |
202 <select name="foo"> | 202 <select name="foo"> |
203 <option value="1">1</option> | 203 <option value="1">1</option> |
204 <option value="2">2</option> | 204 <option value="2">2</option> |
205 <option value="3">3</option> | 205 <option value="3">3</option> |
206 </select> | 206 </select> |
207 </p></form>""", unicode(html)) | 207 </p></form>""", html.render()) |
208 | 208 |
209 def test_fill_select_single_value_auto(self): | 209 def test_fill_select_single_value_auto(self): |
210 html = HTML("""<form><p> | 210 html = HTML("""<form><p> |
211 <select name="foo"> | 211 <select name="foo"> |
212 <option>1</option> | 212 <option>1</option> |
218 <select name="foo"> | 218 <select name="foo"> |
219 <option selected="selected">1</option> | 219 <option selected="selected">1</option> |
220 <option>2</option> | 220 <option>2</option> |
221 <option>3</option> | 221 <option>3</option> |
222 </select> | 222 </select> |
223 </p></form>""", unicode(html)) | 223 </p></form>""", html.render()) |
224 | 224 |
225 def test_fill_select_single_value_defined(self): | 225 def test_fill_select_single_value_defined(self): |
226 html = HTML("""<form><p> | 226 html = HTML("""<form><p> |
227 <select name="foo"> | 227 <select name="foo"> |
228 <option value="1">1</option> | 228 <option value="1">1</option> |
234 <select name="foo"> | 234 <select name="foo"> |
235 <option value="1" selected="selected">1</option> | 235 <option value="1" selected="selected">1</option> |
236 <option value="2">2</option> | 236 <option value="2">2</option> |
237 <option value="3">3</option> | 237 <option value="3">3</option> |
238 </select> | 238 </select> |
239 </p></form>""", unicode(html)) | 239 </p></form>""", html.render()) |
240 | 240 |
241 def test_fill_select_multi_value_auto(self): | 241 def test_fill_select_multi_value_auto(self): |
242 html = HTML("""<form><p> | 242 html = HTML("""<form><p> |
243 <select name="foo" multiple> | 243 <select name="foo" multiple> |
244 <option>1</option> | 244 <option>1</option> |
250 <select name="foo" multiple="multiple"> | 250 <select name="foo" multiple="multiple"> |
251 <option selected="selected">1</option> | 251 <option selected="selected">1</option> |
252 <option>2</option> | 252 <option>2</option> |
253 <option selected="selected">3</option> | 253 <option selected="selected">3</option> |
254 </select> | 254 </select> |
255 </p></form>""", unicode(html)) | 255 </p></form>""", html.render()) |
256 | 256 |
257 def test_fill_select_multi_value_defined(self): | 257 def test_fill_select_multi_value_defined(self): |
258 html = HTML("""<form><p> | 258 html = HTML("""<form><p> |
259 <select name="foo" multiple> | 259 <select name="foo" multiple> |
260 <option value="1">1</option> | 260 <option value="1">1</option> |
266 <select name="foo" multiple="multiple"> | 266 <select name="foo" multiple="multiple"> |
267 <option value="1" selected="selected">1</option> | 267 <option value="1" selected="selected">1</option> |
268 <option value="2">2</option> | 268 <option value="2">2</option> |
269 <option value="3" selected="selected">3</option> | 269 <option value="3" selected="selected">3</option> |
270 </select> | 270 </select> |
271 </p></form>""", unicode(html)) | 271 </p></form>""", html.render()) |
272 | 272 |
273 def test_fill_option_segmented_text(self): | 273 def test_fill_option_segmented_text(self): |
274 html = MarkupTemplate("""<form> | 274 html = MarkupTemplate("""<form> |
275 <select name="foo"> | 275 <select name="foo"> |
276 <option value="1">foo $x</option> | 276 <option value="1">foo $x</option> |
278 </form>""").generate(x=1) | HTMLFormFiller(data={'foo': '1'}) | 278 </form>""").generate(x=1) | HTMLFormFiller(data={'foo': '1'}) |
279 self.assertEquals("""<form> | 279 self.assertEquals("""<form> |
280 <select name="foo"> | 280 <select name="foo"> |
281 <option value="1" selected="selected">foo 1</option> | 281 <option value="1" selected="selected">foo 1</option> |
282 </select> | 282 </select> |
283 </form>""", unicode(html)) | 283 </form>""", html.render()) |
284 | 284 |
285 def test_fill_option_segmented_text_no_value(self): | 285 def test_fill_option_segmented_text_no_value(self): |
286 html = MarkupTemplate("""<form> | 286 html = MarkupTemplate("""<form> |
287 <select name="foo"> | 287 <select name="foo"> |
288 <option>foo $x bar</option> | 288 <option>foo $x bar</option> |
290 </form>""").generate(x=1) | HTMLFormFiller(data={'foo': 'foo 1 bar'}) | 290 </form>""").generate(x=1) | HTMLFormFiller(data={'foo': 'foo 1 bar'}) |
291 self.assertEquals("""<form> | 291 self.assertEquals("""<form> |
292 <select name="foo"> | 292 <select name="foo"> |
293 <option selected="selected">foo 1 bar</option> | 293 <option selected="selected">foo 1 bar</option> |
294 </select> | 294 </select> |
295 </form>""", unicode(html)) | 295 </form>""", html.render()) |
296 | 296 |
297 def test_fill_option_unicode_value(self): | 297 def test_fill_option_unicode_value(self): |
298 html = HTML(u"""<form> | 298 html = HTML("""<form> |
299 <select name="foo"> | 299 <select name="foo"> |
300 <option value="ö">foo</option> | 300 <option value="ö">foo</option> |
301 </select> | 301 </select> |
302 </form>""") | HTMLFormFiller(data={'foo': u'ö'}) | 302 </form>""") | HTMLFormFiller(data={'foo': u'ö'}) |
303 self.assertEquals(u"""<form> | 303 self.assertEquals(u"""<form> |
304 <select name="foo"> | 304 <select name="foo"> |
305 <option value="ö" selected="selected">foo</option> | 305 <option value="ö" selected="selected">foo</option> |
306 </select> | 306 </select> |
307 </form>""", unicode(html)) | 307 </form>""", html.render(encoding=None)) |
308 | |
309 def test_fill_input_password_disabled(self): | |
310 html = HTML("""<form><p> | |
311 <input type="password" name="pass" /> | |
312 </p></form>""") | HTMLFormFiller(data={'pass': 'bar'}) | |
313 self.assertEquals("""<form><p> | |
314 <input type="password" name="pass"/> | |
315 </p></form>""", html.render()) | |
316 | |
317 def test_fill_input_password_enabled(self): | |
318 html = HTML("""<form><p> | |
319 <input type="password" name="pass" /> | |
320 </p></form>""") | HTMLFormFiller(data={'pass': '1234'}, passwords=True) | |
321 self.assertEquals("""<form><p> | |
322 <input type="password" name="pass" value="1234"/> | |
323 </p></form>""", html.render()) | |
308 | 324 |
309 | 325 |
310 class HTMLSanitizerTestCase(unittest.TestCase): | 326 class HTMLSanitizerTestCase(unittest.TestCase): |
311 | 327 |
312 def test_sanitize_unchanged(self): | 328 def test_sanitize_unchanged(self): |
313 html = HTML('<a href="#">fo<br />o</a>') | 329 html = HTML('<a href="#">fo<br />o</a>') |
314 self.assertEquals(u'<a href="#">fo<br/>o</a>', | 330 self.assertEquals('<a href="#">fo<br/>o</a>', |
315 unicode(html | HTMLSanitizer())) | 331 (html | HTMLSanitizer()).render()) |
332 html = HTML('<a href="#with:colon">foo</a>') | |
333 self.assertEquals('<a href="#with:colon">foo</a>', | |
334 (html | HTMLSanitizer()).render()) | |
316 | 335 |
317 def test_sanitize_escape_text(self): | 336 def test_sanitize_escape_text(self): |
318 html = HTML('<a href="#">fo&</a>') | 337 html = HTML('<a href="#">fo&</a>') |
319 self.assertEquals(u'<a href="#">fo&</a>', | 338 self.assertEquals('<a href="#">fo&</a>', |
320 unicode(html | HTMLSanitizer())) | 339 (html | HTMLSanitizer()).render()) |
321 html = HTML('<a href="#"><foo></a>') | 340 html = HTML('<a href="#"><foo></a>') |
322 self.assertEquals(u'<a href="#"><foo></a>', | 341 self.assertEquals('<a href="#"><foo></a>', |
323 unicode(html | HTMLSanitizer())) | 342 (html | HTMLSanitizer()).render()) |
324 | 343 |
325 def test_sanitize_entityref_text(self): | 344 def test_sanitize_entityref_text(self): |
326 html = HTML('<a href="#">foö</a>') | 345 html = HTML('<a href="#">foö</a>') |
327 self.assertEquals(u'<a href="#">foö</a>', | 346 self.assertEquals(u'<a href="#">foö</a>', |
328 unicode(html | HTMLSanitizer())) | 347 (html | HTMLSanitizer()).render(encoding=None)) |
329 | 348 |
330 def test_sanitize_escape_attr(self): | 349 def test_sanitize_escape_attr(self): |
331 html = HTML('<div title="<foo>"></div>') | 350 html = HTML('<div title="<foo>"></div>') |
332 self.assertEquals(u'<div title="<foo>"/>', | 351 self.assertEquals('<div title="<foo>"/>', |
333 unicode(html | HTMLSanitizer())) | 352 (html | HTMLSanitizer()).render()) |
334 | 353 |
335 def test_sanitize_close_empty_tag(self): | 354 def test_sanitize_close_empty_tag(self): |
336 html = HTML('<a href="#">fo<br>o</a>') | 355 html = HTML('<a href="#">fo<br>o</a>') |
337 self.assertEquals(u'<a href="#">fo<br/>o</a>', | 356 self.assertEquals('<a href="#">fo<br/>o</a>', |
338 unicode(html | HTMLSanitizer())) | 357 (html | HTMLSanitizer()).render()) |
339 | 358 |
340 def test_sanitize_invalid_entity(self): | 359 def test_sanitize_invalid_entity(self): |
341 html = HTML('&junk;') | 360 html = HTML('&junk;') |
342 self.assertEquals('&junk;', unicode(html | HTMLSanitizer())) | 361 self.assertEquals('&junk;', (html | HTMLSanitizer()).render()) |
343 | 362 |
344 def test_sanitize_remove_script_elem(self): | 363 def test_sanitize_remove_script_elem(self): |
345 html = HTML('<script>alert("Foo")</script>') | 364 html = HTML('<script>alert("Foo")</script>') |
346 self.assertEquals(u'', unicode(html | HTMLSanitizer())) | 365 self.assertEquals('', (html | HTMLSanitizer()).render()) |
347 html = HTML('<SCRIPT SRC="http://example.com/"></SCRIPT>') | 366 html = HTML('<SCRIPT SRC="http://example.com/"></SCRIPT>') |
348 self.assertEquals(u'', unicode(html | HTMLSanitizer())) | 367 self.assertEquals('', (html | HTMLSanitizer()).render()) |
349 self.assertRaises(ParseError, HTML, '<SCR\0IPT>alert("foo")</SCR\0IPT>') | 368 self.assertRaises(ParseError, HTML, '<SCR\0IPT>alert("foo")</SCR\0IPT>') |
350 self.assertRaises(ParseError, HTML, | 369 self.assertRaises(ParseError, HTML, |
351 '<SCRIPT&XYZ SRC="http://example.com/"></SCRIPT>') | 370 '<SCRIPT&XYZ SRC="http://example.com/"></SCRIPT>') |
352 | 371 |
353 def test_sanitize_remove_onclick_attr(self): | 372 def test_sanitize_remove_onclick_attr(self): |
354 html = HTML('<div onclick=\'alert("foo")\' />') | 373 html = HTML('<div onclick=\'alert("foo")\' />') |
355 self.assertEquals(u'<div/>', unicode(html | HTMLSanitizer())) | 374 self.assertEquals('<div/>', (html | HTMLSanitizer()).render()) |
375 | |
376 def test_sanitize_remove_input_password(self): | |
377 html = HTML('<form><input type="password" /></form>') | |
378 self.assertEquals('<form/>', (html | HTMLSanitizer()).render()) | |
356 | 379 |
357 def test_sanitize_remove_comments(self): | 380 def test_sanitize_remove_comments(self): |
358 html = HTML('''<div><!-- conditional comment crap --></div>''') | 381 html = HTML('''<div><!-- conditional comment crap --></div>''') |
359 self.assertEquals(u'<div/>', unicode(html | HTMLSanitizer())) | 382 self.assertEquals('<div/>', (html | HTMLSanitizer()).render()) |
360 | 383 |
361 def test_sanitize_remove_style_scripts(self): | 384 def test_sanitize_remove_style_scripts(self): |
362 sanitizer = HTMLSanitizer(safe_attrs=HTMLSanitizer.SAFE_ATTRS | set(['style'])) | 385 sanitizer = HTMLSanitizer(safe_attrs=HTMLSanitizer.SAFE_ATTRS | set(['style'])) |
363 # Inline style with url() using javascript: scheme | 386 # Inline style with url() using javascript: scheme |
364 html = HTML('<DIV STYLE=\'background: url(javascript:alert("foo"))\'>') | 387 html = HTML('<DIV STYLE=\'background: url(javascript:alert("foo"))\'>') |
365 self.assertEquals(u'<div/>', unicode(html | sanitizer)) | 388 self.assertEquals('<div/>', (html | sanitizer).render()) |
366 # Inline style with url() using javascript: scheme, using control char | 389 # Inline style with url() using javascript: scheme, using control char |
367 html = HTML('<DIV STYLE=\'background: url(javascript:alert("foo"))\'>') | 390 html = HTML('<DIV STYLE=\'background: url(javascript:alert("foo"))\'>') |
368 self.assertEquals(u'<div/>', unicode(html | sanitizer)) | 391 self.assertEquals('<div/>', (html | sanitizer).render()) |
369 # Inline style with url() using javascript: scheme, in quotes | 392 # Inline style with url() using javascript: scheme, in quotes |
370 html = HTML('<DIV STYLE=\'background: url("javascript:alert(foo)")\'>') | 393 html = HTML('<DIV STYLE=\'background: url("javascript:alert(foo)")\'>') |
371 self.assertEquals(u'<div/>', unicode(html | sanitizer)) | 394 self.assertEquals('<div/>', (html | sanitizer).render()) |
372 # IE expressions in CSS not allowed | 395 # IE expressions in CSS not allowed |
373 html = HTML('<DIV STYLE=\'width: expression(alert("foo"));\'>') | 396 html = HTML('<DIV STYLE=\'width: expression(alert("foo"));\'>') |
374 self.assertEquals(u'<div/>', unicode(html | sanitizer)) | 397 self.assertEquals('<div/>', (html | sanitizer).render()) |
375 html = HTML('<DIV STYLE=\'width: e/**/xpression(alert("foo"));\'>') | 398 html = HTML('<DIV STYLE=\'width: e/**/xpression(alert("foo"));\'>') |
376 self.assertEquals(u'<div/>', unicode(html | sanitizer)) | 399 self.assertEquals('<div/>', (html | sanitizer).render()) |
377 html = HTML('<DIV STYLE=\'background: url(javascript:alert("foo"));' | 400 html = HTML('<DIV STYLE=\'background: url(javascript:alert("foo"));' |
378 'color: #fff\'>') | 401 'color: #fff\'>') |
379 self.assertEquals(u'<div style="color: #fff"/>', | 402 self.assertEquals('<div style="color: #fff"/>', |
380 unicode(html | sanitizer)) | 403 (html | sanitizer).render()) |
381 # Inline style with url() using javascript: scheme, using unicode | 404 # Inline style with url() using javascript: scheme, using unicode |
382 # escapes | 405 # escapes |
383 html = HTML('<DIV STYLE=\'background: \\75rl(javascript:alert("foo"))\'>') | 406 html = HTML('<DIV STYLE=\'background: \\75rl(javascript:alert("foo"))\'>') |
384 self.assertEquals(u'<div/>', unicode(html | sanitizer)) | 407 self.assertEquals('<div/>', (html | sanitizer).render()) |
385 html = HTML('<DIV STYLE=\'background: \\000075rl(javascript:alert("foo"))\'>') | 408 html = HTML('<DIV STYLE=\'background: \\000075rl(javascript:alert("foo"))\'>') |
386 self.assertEquals(u'<div/>', unicode(html | sanitizer)) | 409 self.assertEquals('<div/>', (html | sanitizer).render()) |
387 html = HTML('<DIV STYLE=\'background: \\75 rl(javascript:alert("foo"))\'>') | 410 html = HTML('<DIV STYLE=\'background: \\75 rl(javascript:alert("foo"))\'>') |
388 self.assertEquals(u'<div/>', unicode(html | sanitizer)) | 411 self.assertEquals('<div/>', (html | sanitizer).render()) |
389 html = HTML('<DIV STYLE=\'background: \\000075 rl(javascript:alert("foo"))\'>') | 412 html = HTML('<DIV STYLE=\'background: \\000075 rl(javascript:alert("foo"))\'>') |
390 self.assertEquals(u'<div/>', unicode(html | sanitizer)) | 413 self.assertEquals('<div/>', (html | sanitizer).render()) |
391 html = HTML('<DIV STYLE=\'background: \\000075\r\nrl(javascript:alert("foo"))\'>') | 414 html = HTML('<DIV STYLE=\'background: \\000075\r\nrl(javascript:alert("foo"))\'>') |
392 self.assertEquals(u'<div/>', unicode(html | sanitizer)) | 415 self.assertEquals('<div/>', (html | sanitizer).render()) |
416 | |
417 def test_sanitize_remove_style_phishing(self): | |
418 sanitizer = HTMLSanitizer(safe_attrs=HTMLSanitizer.SAFE_ATTRS | set(['style'])) | |
419 # The position property is not allowed | |
420 html = HTML('<div style="position:absolute;top:0"></div>') | |
421 self.assertEquals('<div style="top:0"/>', (html | sanitizer).render()) | |
422 # Normal margins get passed through | |
423 html = HTML('<div style="margin:10px 20px"></div>') | |
424 self.assertEquals('<div style="margin:10px 20px"/>', | |
425 (html | sanitizer).render()) | |
426 # But not negative margins | |
427 html = HTML('<div style="margin:-1000px 0 0"></div>') | |
428 self.assertEquals('<div/>', (html | sanitizer).render()) | |
429 html = HTML('<div style="margin-left:-2000px 0 0"></div>') | |
430 self.assertEquals('<div/>', (html | sanitizer).render()) | |
431 html = HTML('<div style="margin-left:1em 1em 1em -4000px"></div>') | |
432 self.assertEquals('<div/>', (html | sanitizer).render()) | |
393 | 433 |
394 def test_sanitize_remove_src_javascript(self): | 434 def test_sanitize_remove_src_javascript(self): |
395 html = HTML('<img src=\'javascript:alert("foo")\'>') | 435 html = HTML('<img src=\'javascript:alert("foo")\'>') |
396 self.assertEquals(u'<img/>', unicode(html | HTMLSanitizer())) | 436 self.assertEquals('<img/>', (html | HTMLSanitizer()).render()) |
397 # Case-insensitive protocol matching | 437 # Case-insensitive protocol matching |
398 html = HTML('<IMG SRC=\'JaVaScRiPt:alert("foo")\'>') | 438 html = HTML('<IMG SRC=\'JaVaScRiPt:alert("foo")\'>') |
399 self.assertEquals(u'<img/>', unicode(html | HTMLSanitizer())) | 439 self.assertEquals('<img/>', (html | HTMLSanitizer()).render()) |
400 # Grave accents (not parsed) | 440 # Grave accents (not parsed) |
401 self.assertRaises(ParseError, HTML, | 441 self.assertRaises(ParseError, HTML, |
402 '<IMG SRC=`javascript:alert("RSnake says, \'foo\'")`>') | 442 '<IMG SRC=`javascript:alert("RSnake says, \'foo\'")`>') |
403 # Protocol encoded using UTF-8 numeric entities | 443 # Protocol encoded using UTF-8 numeric entities |
404 html = HTML('<IMG SRC=\'javascri' | 444 html = HTML('<IMG SRC=\'javascri' |
405 'pt:alert("foo")\'>') | 445 'pt:alert("foo")\'>') |
406 self.assertEquals(u'<img/>', unicode(html | HTMLSanitizer())) | 446 self.assertEquals('<img/>', (html | HTMLSanitizer()).render()) |
407 # Protocol encoded using UTF-8 numeric entities without a semicolon | 447 # Protocol encoded using UTF-8 numeric entities without a semicolon |
408 # (which is allowed because the max number of digits is used) | 448 # (which is allowed because the max number of digits is used) |
409 html = HTML('<IMG SRC=\'java' | 449 html = HTML('<IMG SRC=\'java' |
410 'script' | 450 'script' |
411 ':alert("foo")\'>') | 451 ':alert("foo")\'>') |
412 self.assertEquals(u'<img/>', unicode(html | HTMLSanitizer())) | 452 self.assertEquals('<img/>', (html | HTMLSanitizer()).render()) |
413 # Protocol encoded using UTF-8 numeric hex entities without a semicolon | 453 # Protocol encoded using UTF-8 numeric hex entities without a semicolon |
414 # (which is allowed because the max number of digits is used) | 454 # (which is allowed because the max number of digits is used) |
415 html = HTML('<IMG SRC=\'javascri' | 455 html = HTML('<IMG SRC=\'javascri' |
416 'pt:alert("foo")\'>') | 456 'pt:alert("foo")\'>') |
417 self.assertEquals(u'<img/>', unicode(html | HTMLSanitizer())) | 457 self.assertEquals('<img/>', (html | HTMLSanitizer()).render()) |
418 # Embedded tab character in protocol | 458 # Embedded tab character in protocol |
419 html = HTML('<IMG SRC=\'jav\tascript:alert("foo");\'>') | 459 html = HTML('<IMG SRC=\'jav\tascript:alert("foo");\'>') |
420 self.assertEquals(u'<img/>', unicode(html | HTMLSanitizer())) | 460 self.assertEquals('<img/>', (html | HTMLSanitizer()).render()) |
421 # Embedded tab character in protocol, but encoded this time | 461 # Embedded tab character in protocol, but encoded this time |
422 html = HTML('<IMG SRC=\'jav	ascript:alert("foo");\'>') | 462 html = HTML('<IMG SRC=\'jav	ascript:alert("foo");\'>') |
423 self.assertEquals(u'<img/>', unicode(html | HTMLSanitizer())) | 463 self.assertEquals('<img/>', (html | HTMLSanitizer()).render()) |
424 | 464 |
425 | 465 |
426 def suite(): | 466 def suite(): |
427 suite = unittest.TestSuite() | 467 suite = unittest.TestSuite() |
428 suite.addTest(doctest.DocTestSuite(HTMLFormFiller.__module__)) | 468 suite.addTest(doctest.DocTestSuite(HTMLFormFiller.__module__)) |
429 suite.addTest(unittest.makeSuite(HTMLFormFillerTestCase, 'test')) | 469 suite.addTest(unittest.makeSuite(HTMLFormFillerTestCase, 'test')) |
430 suite.addTest(unittest.makeSuite(HTMLSanitizerTestCase, 'test')) | 470 suite.addTest(unittest.makeSuite(HTMLSanitizerTestCase, 'test')) |
431 return suite | 471 return suite |
432 | 472 |
473 | |
433 if __name__ == '__main__': | 474 if __name__ == '__main__': |
434 unittest.main(defaultTest='suite') | 475 unittest.main(defaultTest='suite') |