WIP: Note editing, markdown to html
[oweals/karmaworld.git] / karmaworld / apps / wysihtml5 / static / wysihtml5 / wysihtml-0.4.17 / test / dom / parse_test.js
1 if (wysihtml5.browser.supported()) {
2
3   module("wysihtml5.dom.parse", {
4     sanitize: function(html, rules, context, cleanUp, uneditableClass) {
5       return wysihtml5.dom.parse(html, {
6         "rules": rules,
7         "cleanUp": cleanUp,
8         "context": context,
9         "uneditableClass": uneditableClass
10       });
11     },
12
13     equal: function(actual, expected, message) {
14       return QUnit.assert.htmlEqual(actual, expected, message);
15     }
16   });
17
18   test("Simple tests using plain tags only", function() {
19     var rules = {
20       tags: {
21         p:      "div",
22         script: undefined,
23         div:    {}
24       }
25     };
26
27     this.equal(
28       this.sanitize("<i id=\"foo\">bar</i>", rules),
29       "<span>bar</span>",
30       "Unknown tag gets renamed to span"
31     );
32
33     this.equal(
34       this.sanitize("<p>foo</p>", rules),
35       "<div>foo</div>",
36       "Known tag gets renamed to it's corresponding conversion"
37     );
38
39     this.equal(
40       this.sanitize("<script>window;</script>", rules),
41       "",
42       "Forbidden tag gets correctly removed"
43     );
44
45     this.equal(
46       this.sanitize("foobar", rules),
47       "foobar",
48       "Plain text is kept"
49     );
50
51     this.equal(
52       this.sanitize("<table><tbody><tr><td>I'm a table!</td></tr></tbody></table>"),
53       "<span><span><span><span>I'm a table!</span></span></span></span>",
54       "Passing no conversion renames all into <span> elements"
55     );
56
57     this.equal(
58       this.sanitize("<p>foobar<br></p>", { tags: { p: true, br: true } }),
59       "<p>foobar<br></p>",
60       "Didn't rewrite the HTML"
61     );
62
63     this.equal(
64       this.sanitize("<div><!-- COMMENT -->foo</div>"),
65       "<span>foo</span>",
66       "Stripped out comments"
67     );
68     
69     this.equal(
70       this.sanitize("<article>foo</article>", { tags: { article: true } }),
71       "<article>foo</article>",
72       "Check html5 tags"
73     );
74     
75     this.equal(
76       this.sanitize("<!DOCTYPE html><p>html5 doctype</p>", { tags: { p: true } }),
77       "<p>html5 doctype</p>",
78       "Stripped out doctype"
79     );
80   });
81
82
83   test("Advanced tests using tags and attributes", function() {
84     var rules = {
85       tags: {
86         img: {
87           set_attributes: { alt: "foo", border: "1" },
88           check_attributes: { src: "url", width: "numbers", height: "numbers", border: "numbers" }
89         },
90         a: {
91           rename_tag: "i",
92           set_attributes: { title: "" }
93         },
94         video: undefined,
95         h1: { rename_tag: "h2" },
96         h2: true,
97         h3: undefined
98       }
99     };
100
101     this.equal(
102       this.sanitize(
103         '<h1 id="main-headline" >take this you snorty little sanitizer</h1>' +
104         '<h2>yes, you!</h2>' +
105         '<h3>i\'m old and ready to die</h3>' +
106         '<div><video src="pr0n.avi">foobar</video><img src="http://foo.gif" height="10" width="10"><img src="/foo.gif"></div>' +
107         '<div><a href="http://www.google.de"></a></div>',
108         rules
109       ),
110       '<h2>take this you snorty little sanitizer</h2>' +
111       '<h2>yes, you!</h2>' +
112       '<span><img alt="foo" border="1" src="http://foo.gif" height="10" width="10"><img alt="foo" border="1"></span>' +
113       '<span><i title=""></i></span>'
114     );
115   });
116   test("Attribute check of 'url' cleans up", function() {
117     var rules = {
118       tags: {
119         img: {
120           check_attributes: { src: "url" }
121         }
122       }
123     };
124
125     this.equal(
126       this.sanitize(
127         '<img src="http://url.gif">' +
128         '<img src="/path/to/absolute%20href.gif">' +
129         '<img src="mango time">',
130         rules
131       ),
132       '<img src="http://url.gif"><img><img>'
133     );
134   });
135
136   test("Attribute check of 'src' cleans up", function() {
137     var rules = {
138       tags: {
139         img: {
140           check_attributes: { src: "src" }
141         }
142       }
143     };
144
145     this.equal(
146       this.sanitize(
147         '<img src="HTTP://url.gif">' +
148         '<img src="/path/to/absolute%20href.gif">' +
149         '<img src="mailto:christopher@foobar.com">' +
150         '<img src="mango time">',
151         rules
152       ),
153       '<img src="http://url.gif">' +
154       '<img src="/path/to/absolute%20href.gif">' +
155       '<img>' +
156       '<img>'
157     );
158   });
159   
160   test("Attribute check of 'href' cleans up", function() {
161     var rules = {
162       tags: {
163         a: {
164           check_attributes: { href: "href" }
165         }
166       }
167     };
168
169     this.equal(
170       this.sanitize(
171         '<a href="/foobar"></a>' +
172         '<a href="HTTPS://google.com"></a>' +
173         '<a href="http://google.com"></a>' +
174         '<a href="MAILTO:christopher@foobar.com"></a>' +
175         '<a href="mango time"></a>' +
176         '<a href="ftp://google.com"></a>',
177         rules
178       ),
179       '<a href="/foobar"></a>' +
180       '<a href="https://google.com"></a>' +
181       '<a href="http://google.com"></a>' +
182       '<a href="mailto:christopher@foobar.com"></a>' +
183       '<a></a>' +
184       '<a></a>'
185     );
186   });
187
188   test("Bug in IE8 where invalid html causes duplicated content", function() {
189     var rules = {
190       tags: { p: true, span: true, div: true }
191     };
192     
193     var result = this.sanitize('<SPAN><P><SPAN><div>FOO</div>', rules);
194     ok(result.indexOf("FOO") === result.lastIndexOf("FOO"));
195   });
196   
197   
198   test("Bug in IE8 where elements are duplicated when multiple parsed", function() {
199     var rules = {
200       tags: { p: true, span: true, div: true }
201     };
202     
203     var firstResult = this.sanitize('<SPAN><P><SPAN>foo<P></P>', rules);
204     var secondResult = this.sanitize(firstResult, rules);
205     
206     ok(secondResult.indexOf("foo") !== -1);
207     this.equal(firstResult, secondResult);
208     
209     firstResult = this.sanitize('<SPAN><DIV><SPAN>foo<DIV></DIV>', rules);
210     secondResult = this.sanitize(firstResult, rules);
211     
212     ok(secondResult.indexOf("foo") !== -1);
213     this.equal(firstResult, secondResult);
214   });
215   
216   test("Test cleanup mode", function() {
217     var rules = {
218       classes: { a: 1, c: 1 },
219       tags: { span: true, div: true }
220     };
221     
222     this.equal(
223       this.sanitize("<div><span>foo</span></div>", rules, null, true),
224       "<div>foo</div>"
225     );
226     
227     this.equal(
228       this.sanitize("<span><p>foo</p></span>", rules, null, true),
229       "foo"
230     );
231     
232     this.equal(
233       this.sanitize('<span class="a"></span><span class="a">foo</span>', rules, null, true),
234       '<span class="a">foo</span>',
235       "Empty 'span' is correctly removed"
236     );
237     
238     this.equal(
239       this.sanitize('<span><span class="a">1</span> <span class="b">2</span> <span class="c">3</span></span>', rules, null, true),
240       '<span class="a">1</span> 2 <span class="c">3</span>',
241       "Senseless 'span' is correctly removed"
242     );
243   });
244   
245   
246   test("Advanced tests for 'img' elements", function() {
247     var rules = {
248       classes: {
249         "wysiwyg-float-right":  1,
250         "wysiwyg-float-left":   1
251       },
252       tags: {
253         img: {
254           check_attributes: {
255             width:    "numbers",
256             alt:      "alt",
257             src:      "url",
258             height:   "numbers"
259           },
260           add_class: {
261             align: "align_img"
262           }
263         }
264       }
265     };
266
267     this.equal(
268       this.sanitize(
269         '<img src="https://www.xing.com/img/users/1/2/7/f98db1f73.6149675_s4.jpg" alt="Christopher Blum" width="57" height="75" class="wysiwyg-float-right">',
270         rules
271       ),
272       '<img alt="Christopher Blum" class="wysiwyg-float-right" height="75" src="https://www.xing.com/img/users/1/2/7/f98db1f73.6149675_s4.jpg" width="57">'
273     );
274
275     this.equal(
276       this.sanitize(
277         '<img src="https://www.xing.com/img/users/1/2/7/f98db1f73.6149675_s4.jpg" alt="Christopher Blum" width="57" height="75" ALIGN="RIGHT">',
278         rules
279       ),
280       '<img alt="Christopher Blum" class="wysiwyg-float-right" height="75" src="https://www.xing.com/img/users/1/2/7/f98db1f73.6149675_s4.jpg" width="57">'
281     );
282
283     this.equal(
284       this.sanitize(
285         '<img src="https://www.xing.com/img/users/1/2/7/f98db1f73.6149675_s4.jpg" alt="Christopher Blum" width="57" height="75" align="left">',
286         rules
287       ),
288       '<img alt="Christopher Blum" class="wysiwyg-float-left" height="75" src="https://www.xing.com/img/users/1/2/7/f98db1f73.6149675_s4.jpg" width="57">'
289     );
290
291     this.equal(
292       this.sanitize(
293         '<img src="https://www.xing.com/img/users/1/2/7/f98db1f73.6149675_s4.jpg" alt="Christopher Blum" width="57" height="75" align="">',
294         rules
295       ),
296       '<img alt="Christopher Blum" height="75" src="https://www.xing.com/img/users/1/2/7/f98db1f73.6149675_s4.jpg" width="57">'
297     );
298
299     this.equal(
300       this.sanitize(
301         '<img src="/img/users/1/2/7/f98db1f73.6149675_s4.jpg" alt="Christopher Blum" width="57" height="75">',
302         rules
303       ),
304       '<img alt="Christopher Blum" height="75" width="57">'
305     );
306
307     this.equal(
308       this.sanitize(
309         '<img src="file://foobar.jpg" alt="Christopher Blum" width="57" height="75">',
310         rules
311       ),
312       '<img alt="Christopher Blum" height="75" width="57">'
313     );
314
315     this.equal(
316       this.sanitize(
317         '<img src="https://www.xing.com/img/users/1/2/7/f98db1f73.6149675_s4.jpg" width="57" height="75">',
318         rules
319       ),
320       '<img alt="" height="75" src="https://www.xing.com/img/users/1/2/7/f98db1f73.6149675_s4.jpg" width="57">'
321     );
322
323     this.equal(
324       this.sanitize(
325         '<img>',
326         rules
327       ),
328       '<img alt="">'
329     );
330   });
331
332
333   test("Advanced tests for 'br' elements", function() {
334     var rules = {
335       classes: {
336         "wysiwyg-clear-both":   1,
337         "wysiwyg-clear-left":   1,
338         "wysiwyg-clear-right":  1
339       },
340       tags: {
341         div: true,
342         br: {
343           add_class: {
344             clear: "clear_br"
345           }
346         }
347       }
348     };
349
350     this.equal(
351       this.sanitize(
352         '<div>foo<br clear="both">bar</div>',
353         rules
354       ),
355       '<div>foo<br class="wysiwyg-clear-both">bar</div>'
356     );
357
358     this.equal(
359       this.sanitize(
360         '<div>foo<br clear="all">bar</div>',
361         rules
362       ),
363       '<div>foo<br class="wysiwyg-clear-both">bar</div>'
364     );
365
366     this.equal(
367       this.sanitize(
368         '<div>foo<br clear="left" id="foo">bar</div>',
369         rules
370       ),
371       '<div>foo<br class="wysiwyg-clear-left">bar</div>'
372     );
373
374     this.equal(
375       this.sanitize(
376         '<br clear="right">',
377         rules
378       ),
379       '<br class="wysiwyg-clear-right">'
380     );
381
382     this.equal(
383       this.sanitize(
384         '<br clear="">',
385         rules
386       ),
387       '<br>'
388     );
389
390     this.equal(
391       this.sanitize(
392         '<br clear="LEFT">',
393         rules
394       ),
395       '<br class="wysiwyg-clear-left">'
396     );
397     
398     this.equal(
399       this.sanitize(
400         '<br class="wysiwyg-clear-left">',
401         rules
402       ),
403       '<br class="wysiwyg-clear-left">'
404     );
405     
406     this.equal(
407       this.sanitize(
408         '<br clear="left" class="wysiwyg-clear-left">',
409         rules
410       ),
411       '<br class="wysiwyg-clear-left">'
412     );
413     
414     this.equal(
415       this.sanitize(
416         '<br clear="left" class="wysiwyg-clear-left wysiwyg-clear-right">',
417         rules
418       ),
419       '<br class="wysiwyg-clear-left wysiwyg-clear-right">'
420     );
421     
422     this.equal(
423       this.sanitize(
424         '<br clear="left" class="wysiwyg-clear-right">',
425         rules
426       ),
427       '<br class="wysiwyg-clear-left wysiwyg-clear-right">'
428     );
429   });
430   
431   
432   test("Advanced tests for 'font' elements", function() {
433     var rules = {
434       classes: {
435         "wysiwyg-font-size-xx-small": 1,
436         "wysiwyg-font-size-small":    1,
437         "wysiwyg-font-size-medium":   1,
438         "wysiwyg-font-size-large":    1,
439         "wysiwyg-font-size-x-large":  1,
440         "wysiwyg-font-size-xx-large": 1,
441         "wysiwyg-font-size-smaller":  1,
442         "wysiwyg-font-size-larger":   1
443       },
444       tags: {
445         font: {
446           add_class: { size: "size_font" },
447           rename_tag: "span"
448         }
449       }
450     };
451     
452     this.equal(
453       this.sanitize(
454         '<font size="1">foo</font>',
455         rules
456       ),
457       '<span class="wysiwyg-font-size-xx-small">foo</span>'
458     );
459     
460     this.equal(
461       this.sanitize(
462         '<font size="2">foo</font>',
463         rules
464       ),
465       '<span class="wysiwyg-font-size-small">foo</span>'
466     );
467     
468     this.equal(
469       this.sanitize(
470         '<font size="3">foo</font>',
471         rules
472       ),
473       '<span class="wysiwyg-font-size-medium">foo</span>'
474     );
475     
476     this.equal(
477       this.sanitize(
478         '<font size="4">foo</font>',
479         rules
480       ),
481       '<span class="wysiwyg-font-size-large">foo</span>'
482     );
483     
484     this.equal(
485       this.sanitize(
486         '<font size="5">foo</font>',
487         rules
488       ),
489       '<span class="wysiwyg-font-size-x-large">foo</span>'
490     );
491     
492     this.equal(
493       this.sanitize(
494         '<font size="6">foo</font>',
495         rules
496       ),
497       '<span class="wysiwyg-font-size-xx-large">foo</span>'
498     );
499     
500     this.equal(
501       this.sanitize(
502         '<font size="7">foo</font>',
503         rules
504       ),
505       '<span class="wysiwyg-font-size-xx-large">foo</span>'
506     );
507     
508     this.equal(
509       this.sanitize(
510         '<font size="+1">foo</font>',
511         rules
512       ),
513       '<span class="wysiwyg-font-size-larger">foo</span>'
514     );
515     
516     this.equal(
517       this.sanitize(
518         '<font size="-1">foo</font>',
519         rules
520       ),
521       '<span class="wysiwyg-font-size-smaller">foo</span>'
522     );
523   });
524   
525   
526   test("Check whether namespaces are handled correctly", function() {
527     var rules = {
528       tags: {
529         p: true
530       }
531     };
532
533     this.equal(
534       this.sanitize("<o:p>foo</o:p>", rules),
535       "<span>foo</span>",
536       "Unknown tag with namespace gets renamed to span"
537     );
538   });
539   
540   
541   test("Check whether classes are correctly treated", function() {
542     var rules = {
543       classes: {
544         a: 1,
545         c: 1
546       },
547       tags: {
548         footer: "div"
549       }
550     };
551     
552     this.equal(
553       this.sanitize('<header class="a b c">foo</header>', rules),
554       '<span class="a c">foo</span>',
555       "Allowed classes 'a' and 'c' are correctly kept and unknown class 'b' is correctly removed."
556     );
557     
558     this.equal(
559       this.sanitize('<footer class="ab c d" class="a">foo</footer>', rules),
560       '<div class="c">foo</div>',
561       "Allowed classes 'c' is correctly kept and unknown class 'b' is correctly removed."
562     );
563   });
564   
565   test("Check mailto links", function() {
566     var rules = {
567       tags: {
568         a: {
569           check_attributes: {
570             href: "href"
571           }
572         }
573       }
574     };
575     
576
577     this.equal(
578       this.sanitize('<a href="mailto:foo@bar.com">foo</a>', rules),
579       '<a href="mailto:foo@bar.com">foo</a>',
580       "'mailto:' urls are not stripped"
581     );
582   });
583
584   test("Check anchor links", function() {
585     var rules = {
586       tags: {
587         a: {
588           check_attributes: {
589             href: "href"
590           }
591         }
592       }
593     };
594
595     this.equal(
596       this.sanitize('<a href="#anchor">foo</a>', rules),
597       '<a href="#anchor">foo</a>',
598       "'#'-starting anchor urls are not stripped"
599     );
600   });
601   
602   test("Check custom data attributes", function() {
603     var rules = {
604       tags: {
605         span: {
606           check_attributes: {
607             "data-max-width": "numbers"
608           }
609         }
610       }
611     };
612     
613
614     this.equal(
615       this.sanitize('<span data-max-width="24px" data-min-width="25">foo</span>', rules),
616       '<span data-max-width="24">foo</span>',
617       "custom data attributes are not stripped"
618     );
619   });
620   
621   test("Check Firefox misbehavior with tilde characters in urls", function() {
622     var rules = {
623       tags: {
624         a: {
625           set_attributes: {
626             target: "_blank",
627             rel:    "nofollow"
628           },
629           check_attributes: {
630             href:   "url"
631           }
632         }
633       }
634     };
635     
636     // See https://bugzilla.mozilla.org/show_bug.cgi?id=664398
637     //
638     // In Firefox this:
639     //      var d = document.createElement("div");
640     //      d.innerHTML ='<a href="~"></a>';
641     //      d.innerHTML;
642     // will result in:
643     //      <a href="%7E"></a>
644     // which is wrong
645     ok(
646       this.sanitize('<a href="http://google.com/~foo"></a>', rules).indexOf("~") !== -1
647     );
648   });
649   
650   test("Check concatenation of text nodes", function() {
651     var rules = {
652       tags: { span: 1, div: 1 }
653     };
654     
655     var tree = document.createElement("div");
656     tree.appendChild(document.createTextNode("foo "));
657     tree.appendChild(document.createTextNode("bar baz "));
658     tree.appendChild(document.createTextNode("bam! "));
659     
660     var span = document.createElement("span");
661     span.innerHTML = "boobs! hihihi ...";
662     tree.appendChild(span);
663     
664     var result = this.sanitize(tree, rules);
665     equal(result.childNodes.length, 2);
666     equal(result.innerHTML, "foo bar baz bam! <span>boobs! hihihi ...</span>");
667   });
668   
669   test("Check element unwrapping", function() {
670     var rules = {
671       tags: { 
672           div: {
673               unwrap: 1
674           },
675           span: {
676             unwrap: 1
677           }
678        }
679     },
680     input = "<div>Hi,<span> there<span></span>!</span></div>",
681     output = "Hi, there!<br>";
682     this.equal(this.sanitize(input, rules), output);
683   });
684   
685   test("Check spacing when unwrapping elements", function() {
686     var rules = {
687       tags: { 
688           table: {
689               unwrap: 1
690           },
691           td: {
692             unwrap: 1
693           },
694           tr: {
695             unwrap: 1
696           },
697           tbody: {
698             unwrap: 1
699           },
700           ul: {
701             unwrap: 1
702           },
703           li: {
704             unwrap: 1
705           }
706        }
707     },
708     input_list = "<ul><li>This</li><li>is</li><li>a</li><li>list</li></ul>",
709     output_list = "This is a list<br>",
710     input_table = "<table><tbody><tr><td>This</td><td>is</td><td>a</td><td>table</td></tr></tbody></table>",
711     output_table = "This is a table<br>";
712     
713     this.equal(this.sanitize(input_list, rules), output_list, "List unwrapping working ok");
714     this.equal(this.sanitize(input_table, rules), output_table, "Table unwrapping working ok");
715   });
716   
717   test("Test valid type check by attributes", function() {
718     var rules = {
719       "type_definitions": {
720         "valid_image_src": {
721             "attrs": {
722                 "src": /^[^data\:]/i
723             }
724          }
725       },
726       "tags": {
727           "img": {
728               "one_of_type": {
729                   "valid_image_src": 1
730               },
731               "check_attributes": {
732                   "src": "src",
733                   "height": "numbers",
734                   "width": "numbers",
735                   "alt": "alt"
736               }
737           }
738        }
739     },
740     input = '<img src="data:image/gif;base64,R0lGODlhAQABAPAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt="alt" />',
741     input_valid = '<img alt="" src="http://www.asd/a.jpg">',
742     input_valid_2 = '<img src="http://reykjavik.edicy.co/photos/photo02.jpg" alt="" height="243" width="710">';
743     
744     this.equal(this.sanitize(input, rules), "", "Image with data src gets removed");
745     this.equal(this.sanitize(input_valid, rules), input_valid, "Valid image is kept");
746     this.equal(this.sanitize(input_valid_2, rules), input_valid_2, "Valid image is kept2");
747   });
748
749   test("Test valid type check and remove_action", function() {
750     var rules = {
751       "type_definitions": {
752         "valid_element": {
753           "classes": {
754             "testclass": 1
755           }
756         }
757       },
758       "tags": {
759         "div": {
760           "one_of_type": {
761             "valid_element": 1
762           },
763           "check_attributes": {
764             "class": "any"
765           },
766           "remove_action": "rename",
767           "remove_action_rename_to": "span"
768         },
769         "span": {
770           "check_attributes": {
771             "class": "any"
772           }
773         }
774       }
775     },
776     input = '<div class="testclass">Test</div>',
777     input2 = '<div class="otherclass">Test</div>',
778     output2 = '<span class="otherclass">Test</span>';
779     
780     this.equal(this.sanitize(input, rules), input, "Div is kept as having valid class");
781     this.equal(this.sanitize(input2, rules), output2, "Div is renamed to span when type declaration is not met");
782   });
783
784   test("Test valid type definition visible_content_object ", function() {
785     var rules = {
786       "type_definitions": {
787         "visible_content_object": {
788             "methods": {
789                 "has_visible_contet": 1
790             }
791         },
792       },
793       "tags": {
794           'div': {
795               "one_of_type": {
796                   "visible_content_object": 1
797               },
798               "remove_action": "unwrap",
799               "check_attributes": {
800                   "style": "any"
801               }
802           },
803           'img': {
804             "check_attributes": {
805               "src": "any"
806             }
807           },
808           'span': {}
809        }
810     },
811     input1 = '<div></div>',
812     input2 = '<div>   <span>  </span>  </div>',
813     input3 = '<div><img src="pic.jpg"/></div>',
814     input4 = '<div>test</div>',
815     input5 = '<div style="width: 10px; height: 10px;">   <span>  </span>  </div>',
816     tester = document.createElement('div');
817
818     this.equal(this.sanitize(input1, rules), "<br>", "Empty DIV gets removed");
819     this.equal(this.sanitize(input2, rules), "   <span>  </span>  <br>", "DIV with no textual content gets unwrapped");
820
821     this.equal(this.sanitize(input3, rules), input3, "DIV with img inside is kept");
822     this.equal(this.sanitize(input4, rules), input4, "DIV with textual content is kept");
823
824     document.body.appendChild(tester);
825
826     tester.innerHTML = input2;
827     this.equal(this.sanitize(tester, rules).innerHTML, "   <span>  </span>  <br>", "DIV with no dimesions and in dom gets unwrapped");
828
829     tester.innerHTML = input5;
830     this.equal(this.sanitize(tester, rules).innerHTML, input5 , "DIV with dimensions and in dom is kept");
831
832   });
833
834   test("Test keeping comments ", function() {
835     var rules = {
836       "comments": 1
837     },
838     input = 'Test <!-- some comment -->';
839     this.equal(this.sanitize(input, rules), input, "Comments are kept if configured to keep");
840   });
841
842   test("Test global valid attributes for all elements ", function() {
843     var rules = {
844           "attributes": {
845               "id": "any",
846               "data-*": "any"
847           },
848           "tags": {
849             'div': {},
850             'span': {
851               "check_attributes": {
852                 "data-*": "numbers"
853               }
854             }
855           }
856         },
857         rules2 = {
858           "attributes": {
859               "id": "any",
860               "data-*": "any"
861           },
862           "tags": {
863             'div': {}
864           }
865         },
866         input1 = '<div id="test">Test</div>',
867         input2 = '<div class="test">Test</div>',
868         output2 = '<div>Test</div>',
869         input3 = '<div data-name="test" data-value="test">Test</div>',
870         input4 = '<span data-name="test" data-value="1234">Test</span>',
871         output4 = '<span data-value="1234">Test</span>';
872
873     this.equal(this.sanitize(input1, rules), input1, "Global attribute allows id for all elements and div is allowewd tag and kept");
874     this.equal(this.sanitize(input1, rules2), input1, "Global attribute allows id for all elements and div is allowewd tag and kept even if no check_attributes");
875     this.equal(this.sanitize(input2, rules), output2, "Div is kept but attribute 'class' is not allowed locally and globally, so it is removed.");
876     this.equal(this.sanitize(input3, rules), input3, "Global eattribute configuration allows all attributes beginning with 'data-'.");
877     this.equal(this.sanitize(input4, rules), output4, "Local check_attributes overwrites global attributes");
878   
879   });
880
881   test("Test classes blacklist ", function() {
882     var rules = {
883       "classes": "any",
884       "classes_blacklist": {
885         "Apple-interchange-newline": 1
886       },
887       "tags": {
888         'span': {
889         }
890       }
891     },
892     input1 = '<span class="Apple-interchange-newline">Test</span',
893     output1 = '<span>Test</span>',
894     input2 = '<span class="SomeClass">Test</span>',
895     input3 = '<span class="SomeClass Apple-interchange-newline">Test</span>';
896
897     this.equal(this.sanitize(input1, rules), output1, "Blacklist class removed");
898     this.equal(this.sanitize(input2, rules), input2, "Other class kept");
899     this.equal(this.sanitize(input3, rules), input2, "Other class kept, but blacklisted class removed");
900
901   
902   });
903 }