2012-08-13 14:22:32 +00:00
#!/usr/bin/env python
2012-08-14 12:14:25 +00:00
# -*- coding: utf-8 -*-
2012-11-06 12:18:24 +00:00
# This test can be run stand-alone with something like:
# > PYTHONPATH=. python2 openerp/tests/test_misc.py
2012-11-06 11:54:20 +00:00
##############################################################################
#
# OpenERP, Open Source Business Applications
# Copyright (c) 2012-TODAY OpenERP S.A. <http://openerp.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
2012-11-06 12:18:24 +00:00
import unittest2
2012-11-09 12:35:21 +00:00
from openerp . tools import html_sanitize , html_email_clean , append_content_to_html , plaintext2html
2012-08-13 14:22:32 +00:00
2012-11-09 12:35:21 +00:00
HTML_SOURCE = """
2012-08-13 14:22:32 +00:00
< font size = " 2 " style = " color: rgb(31, 31, 31); font-family: monospace; font-variant: normal; line-height: normal; " > test1 < / font >
< div style = " color: rgb(31, 31, 31); font-family: monospace; font-variant: normal; line-height: normal; font-size: 12px; font-style: normal; " >
< b > test2 < / b > < / div > < div style = " color: rgb(31, 31, 31); font-family: monospace; font-variant: normal; line-height: normal; font-size: 12px; " >
< i > test3 < / i > < / div > < div style = " color: rgb(31, 31, 31); font-family: monospace; font-variant: normal; line-height: normal; font-size: 12px; " >
< u > test4 < / u > < / div > < div style = " color: rgb(31, 31, 31); font-family: monospace; font-variant: normal; line-height: normal; font-size: 12px; " >
< strike > test5 < / strike > < / div > < div style = " color: rgb(31, 31, 31); font-family: monospace; font-variant: normal; line-height: normal; " >
< font size = " 5 " > test6 < / font > < / div > < div > < ul > < li > < font color = " #1f1f1f " face = " monospace " size = " 2 " > test7 < / font > < / li > < li >
< font color = " #1f1f1f " face = " monospace " size = " 2 " > test8 < / font > < / li > < / ul > < div > < ol > < li > < font color = " #1f1f1f " face = " monospace " size = " 2 " > test9 < / font >
< / li > < li > < font color = " #1f1f1f " face = " monospace " size = " 2 " > test10 < / font > < / li > < / ol > < / div > < / div >
< blockquote style = " margin: 0 0 0 40px; border: none; padding: 0px; " > < div > < div > < div > < font color = " #1f1f1f " face = " monospace " size = " 2 " >
test11 < / font > < / div > < / div > < / div > < / blockquote > < blockquote style = " margin: 0 0 0 40px; border: none; padding: 0px; " >
< blockquote style = " margin: 0 0 0 40px; border: none; padding: 0px; " > < div > < font color = " #1f1f1f " face = " monospace " size = " 2 " >
test12 < / font > < / div > < div > < font color = " #1f1f1f " face = " monospace " size = " 2 " > < br > < / font > < / div > < / blockquote > < / blockquote >
< font color = " #1f1f1f " face = " monospace " size = " 2 " > < a href = " http://google.com " > google < / a > < / font >
2012-08-13 15:52:05 +00:00
< a href = " javascript:alert( ' malicious code ' ) " > test link < / a >
2012-08-13 14:22:32 +00:00
"""
2012-12-26 16:25:05 +00:00
EDI_LIKE_HTML_SOURCE = """ <div style= " font-family: ' Lucica Grande ' , Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: #FFF; " >
< p > Hello $ { object . partner_id . name } , < / p >
< p > A new invoice is available for you : < / p >
< p style = " border-left: 1px solid #8e0000; margin-left: 30px; " >
& nbsp ; & nbsp ; < strong > REFERENCES < / strong > < br / >
& nbsp ; & nbsp ; Invoice number : < strong > $ { object . number } < / strong > < br / >
& nbsp ; & nbsp ; Invoice total : < strong > $ { object . amount_total } $ { object . currency_id . name } < / strong > < br / >
& nbsp ; & nbsp ; Invoice date : $ { object . date_invoice } < br / >
& nbsp ; & nbsp ; Order reference : $ { object . origin } < br / >
& nbsp ; & nbsp ; Your contact : < a href = " mailto:$ { object.user_id.email or ' ' }?subject=Invoice % 20$ {object.number} " > $ { object . user_id . name } < / a >
< / p >
< br / >
< p > It is also possible to directly pay with Paypal : < / p >
< a style = " margin-left: 120px; " href = " $ {object.paypal_url} " >
< img class = " oe_edi_paypal_button " src = " https://www.paypal.com/en_US/i/btn/btn_paynowCC_LG.gif " / >
< / a >
< br / >
< p > If you have any question , do not hesitate to contact us . < / p >
< p > Thank you for choosing $ { object . company_id . name or ' us ' } ! < / p >
< br / >
< br / >
< div style = " width: 375px; margin: 0px; padding: 0px; background-color: #8E0000; border-top-left-radius: 5px 5px; border-top-right-radius: 5px 5px; background-repeat: repeat no-repeat; " >
< h3 style = " margin: 0px; padding: 2px 14px; font-size: 12px; color: #DDD; " >
< strong style = " text-transform:uppercase; " > $ { object . company_id . name } < / strong > < / h3 >
< / div >
< div style = " width: 347px; margin: 0px; padding: 5px 14px; line-height: 16px; background-color: #F2F2F2; " >
< span style = " color: #222; margin-bottom: 5px; display: block; " >
$ { object . company_id . street } < br / >
$ { object . company_id . street2 } < br / >
$ { object . company_id . zip } $ { object . company_id . city } < br / >
$ { object . company_id . state_id and ( ' %s , ' % object . company_id . state_id . name ) or ' ' } $ { object . company_id . country_id . name or ' ' } < br / >
< / span >
< div style = " margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " >
Phone : & nbsp ; $ { object . company_id . phone }
< / div >
< div >
Web : & nbsp ; < a href = " $ {object.company_id.website} " > $ { object . company_id . website } < / a >
< / div >
< / div >
< / div > < / body > < / html > """
2012-11-09 12:35:21 +00:00
TEXT_MAIL1 = """ I contact you about our meeting for tomorrow. Here is the schedule I propose:
9 AM : brainstorming about our new amazing business app < / span > < / li >
9.45 AM : summary
10 AM : meeting with Fabien to present our app
Is everything ok for you ?
- -
Administrator """
HTML_MAIL1 = """ <div>
< font > < span > I contact you about our meeting for tomorrow . Here is the schedule I propose : < / span > < / font >
< / div >
< div > < ul >
< li > < span > 9 AM : brainstorming about our new amazing business app < / span > < / li >
< li > < span > 9.45 AM : summary < / span > < / li >
< li > < span > 10 AM : meeting with Fabien to present our app < / span > < / li >
< / ul > < / div >
< div > < font > < span > Is everything ok for you ? < / span > < / font > < / div > """
GMAIL_REPLY1_SAN = """ Hello,<div><br></div><div>Ok for me. I am replying directly in gmail, without signature.</div><div><br></div><div>Kind regards,</div><div><br></div><div>Demo.<br><br><div>On Thu, Nov 8, 2012 at 5:29 PM, <span><<a href= " mailto:dummy@example.com " >dummy@example.com</a>></span> wrote:<br><blockquote><div>I contact you about our meeting for tomorrow. Here is the schedule I propose:</div><div><ul><li>9 AM: brainstorming about our new amazing business app</span></li></li>
< li > 9.45 AM : summary < / li > < li > 10 AM : meeting with Fabien to present our app < / li > < / ul > < / div > < div > Is everything ok for you ? < / div >
< div > < p > - - < br > Administrator < / p > < / div >
< div > < p > Log in our portal at : < a href = " http://localhost:8069#action=login&db=mail_1&login=demo " > http : / / localhost : 8069 #action=login&db=mail_1&login=demo</a></p></div>
< / blockquote > < / div > < br > < / div > """
THUNDERBIRD_16_REPLY1_SAN = """ <div>On 11/08/2012 05:29 PM,
< a href = " mailto:dummy@example.com " > dummy @example.com < / a > wrote : < br > < / div >
2012-11-06 12:18:24 +00:00
< blockquote >
2012-11-09 12:35:21 +00:00
< div > I contact you about our meeting for tomorrow . Here is the
schedule I propose : < / div >
< div >
< ul > < li > 9 AM : brainstorming about our new amazing business
app & lt ; / span & gt ; & lt ; / li & gt ; < / li >
< li > 9.45 AM : summary < / li >
< li > 10 AM : meeting with Fabien to present our app < / li >
< / ul > < / div >
< div > Is everything ok for you ? < / div >
< div >
< p > - - < br >
Administrator < / p >
2012-11-06 12:18:24 +00:00
< / div >
< div >
2012-11-09 12:35:21 +00:00
< p > Log in our portal at :
< a href = " http://localhost:8069#action=login&db=mail_1&token=rHdWcUART5PhEnJRaXjH " > http : / / localhost : 8069 #action=login&db=mail_1&token=rHdWcUART5PhEnJRaXjH</a></p>
< / div >
2012-11-06 12:18:24 +00:00
< / blockquote >
2012-11-09 12:35:21 +00:00
Ok for me . I am replying directly below your mail , using
Thunderbird , with a signature . < br > < br >
Did you receive my email about my new laptop , by the way ? < br > < br >
Raoul . < br > < pre > - -
Raoul Grosbedonn & #233;e
2012-11-06 12:18:24 +00:00
< / pre > """
2012-11-07 09:32:01 +00:00
TEXT_TPL = """ Salut Raoul!
Le 28 oct . 2012 à 00 : 02 , Raoul Grosbedon a écrit :
2012-11-06 12:18:24 +00:00
2012-11-07 09:32:01 +00:00
> C ' est sûr que je suis intéressé (quote)!
2012-11-06 12:18:24 +00:00
2012-11-09 12:35:21 +00:00
Trouloulou pouet pouet . Je ne vais quand même pas écrire de vrais mails , non mais ho .
2012-11-06 12:18:24 +00:00
2012-11-07 09:32:01 +00:00
> 2012 / 10 / 27 Bert Tartopoils :
>> Diantre , me disè - je en envoyant un message similaire à Martine , mais comment vas - tu ( quote ) ?
2012-11-06 12:18:24 +00:00
>>
2012-11-07 09:32:01 +00:00
>> A la base le contenu était un vrai mail , mais je l ' ai quand même réécrit pour ce test, histoire de dire que, quand même, on ne met pas n ' importe quoi ici . ( quote )
2012-11-06 12:18:24 +00:00
>>
2012-11-07 09:32:01 +00:00
>> Et sinon bon courage pour trouver tes clefs ( quote ) .
2012-11-06 12:18:24 +00:00
>>
2012-11-07 09:32:01 +00:00
>> Bert TARTOPOILS
>> bert . tartopoils @miam.miam
2012-11-06 12:18:24 +00:00
>>
>
>
> - -
2012-11-07 09:32:01 +00:00
> Raoul Grosbedon
2012-11-06 12:18:24 +00:00
2012-11-07 09:32:01 +00:00
Bert TARTOPOILS
bert . tartopoils @miam.miam
2012-11-06 12:18:24 +00:00
"""
class TestSanitizer ( unittest2 . TestCase ) :
2012-11-14 10:38:49 +00:00
""" Test the html sanitizer that filters html to remove unwanted attributes """
2012-08-13 14:22:32 +00:00
2012-12-26 16:25:05 +00:00
def test_basic_sanitizer ( self ) :
cases = [
( " yop " , " <p>yop</p> " ) , # simple
( " lala<p>yop</p>xxx " , " <div><p>lala</p><p>yop</p>xxx</div> " ) , # trailing text
( " Merci à l ' intérêt pour notre produit.nous vous contacterons bientôt. Merci " ,
u " <p>Merci à l ' intérêt pour notre produit.nous vous contacterons bientôt. Merci</p> " ) , # unicode
]
for content , expected in cases :
html = html_sanitize ( content )
self . assertEqual ( html , expected , ' html_sanitize is broken ' )
2012-11-06 11:54:20 +00:00
2012-12-26 16:25:05 +00:00
def test_evil_malicious_code ( self ) :
2012-12-26 16:43:54 +00:00
# taken from https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Tests
2012-12-26 16:25:05 +00:00
cases = [
( " <IMG SRC=javascript:alert( ' XSS ' )> " ) , # no quotes and semicolons
( " <IMG SRC=javascript:alert('XSS')> " ) , # UTF-8 Unicode encoding
( " <IMG SRC=javascript:alert('XSS')> " ) , # hex encoding
( " <IMG SRC= \" jav
ascript:alert( ' XSS ' ); \" > " ) , # embedded carriage return
( " <IMG SRC= \" jav
ascript:alert( ' XSS ' ); \" > " ) , # embedded newline
( " <IMG SRC= \" jav ascript:alert( ' XSS ' ); \" > " ) , # embedded tab
( " <IMG SRC= \" jav	ascript:alert( ' XSS ' ); \" > " ) , # embedded encoded tab
( " <IMG SRC= \"  javascript:alert( ' XSS ' ); \" > " ) , # spaces and meta-characters
( " <IMG SRC= \" javascript:alert( ' XSS ' ) \" " ) , # half-open html
( " <IMG \" \" \" ><SCRIPT>alert( \" XSS \" )</SCRIPT> \" > " ) , # malformed tag
( " <SCRIPT/XSS SRC= \" http://ha.ckers.org/xss.js \" ></SCRIPT> " ) , # non-alpha-non-digits
( " <SCRIPT/SRC= \" http://ha.ckers.org/xss.js \" ></SCRIPT> " ) , # non-alpha-non-digits
( " <<SCRIPT>alert( \" XSS \" );//<</SCRIPT> " ) , # extraneous open brackets
( " <SCRIPT SRC=http://ha.ckers.org/xss.js?< B > " ) , # non-closing script tags
( " <INPUT TYPE= \" IMAGE \" SRC= \" javascript:alert( ' XSS ' ); \" > " ) , # input image
( " <BODY BACKGROUND= \" javascript:alert( ' XSS ' ) \" > " ) , # body image
( " <IMG DYNSRC= \" javascript:alert( ' XSS ' ) \" > " ) , # img dynsrc
( " <IMG LOWSRC= \" javascript:alert( ' XSS ' ) \" > " ) , # img lowsrc
( " <TABLE BACKGROUND= \" javascript:alert( ' XSS ' ) \" > " ) , # table
( " <TABLE><TD BACKGROUND= \" javascript:alert( ' XSS ' ) \" > " ) , # td
( " <DIV STYLE= \" background-image: url(javascript:alert( ' XSS ' )) \" > " ) , # div background
( " <DIV STYLE= \" background-image: \007 5 \007 2 \006 C \002 8 ' \006 a \006 1 \007 6 \006 1 \007 3 \006 3 \007 2 \006 9 \007 0 \007 4 \003 a \006 1 \006 c \006 5 \007 2 \007 4 \002 8.1027 \005 8.1053 \005 3 \002 7 \002 9 ' \002 9 \" > " ) , # div background with unicoded exploit
( " <DIV STYLE= \" background-image: url(javascript:alert( ' XSS ' )) \" > " ) , # div background + extra characters
( " <IMG SRC= ' vbscript:msgbox( \" XSS \" ) ' > " ) , # VBscrip in an image
( " <BODY ONLOAD=alert( ' XSS ' )> " ) , # event handler
( " <BR SIZE= \" & { alert( ' XSS ' )} \ > " ) , # & javascript includes
( " <LINK REL= \" stylesheet \" HREF= \" javascript:alert( ' XSS ' ); \" > " ) , # style sheet
( " <LINK REL= \" stylesheet \" HREF= \" http://ha.ckers.org/xss.css \" > " ) , # remote style sheet
( " <STYLE>@import ' http://ha.ckers.org/xss.css ' ;</STYLE> " ) , # remote style sheet 2
( " <META HTTP-EQUIV= \" Link \" Content= \" <http://ha.ckers.org/xss.css>; REL=stylesheet \" > " ) , # remote style sheet 3
( " <STYLE>BODY { -moz-binding:url( \" http://ha.ckers.org/xssmoz.xml#xss \" )}</STYLE> " ) , # remote style sheet 4
( " <IMG STYLE= \" xss:expr/*XSS*/ession(alert( ' XSS ' )) \" > " ) , # style attribute using a comment to break up expression
( """ <!--[if gte IE 4]>
< SCRIPT > alert ( ' XSS ' ) ; < / SCRIPT >
< ! [ endif ] - - > """ ), # down-level hidden block
]
for content in cases :
html = html_sanitize ( content )
self . assertNotIn ( ' javascript ' , html , ' html_sanitize did not remove a malicious javascript ' )
self . assertTrue ( ' ha.ckers.org ' not in html or ' http://ha.ckers.org/xss.css ' in html , ' html_sanitize did not remove a malicious code in %s ( %s ) ' % ( content , html ) )
2012-11-06 11:54:20 +00:00
2012-11-14 10:38:49 +00:00
def test_html ( self ) :
sanitized_html = html_sanitize ( HTML_SOURCE )
2012-12-26 16:25:05 +00:00
for tag in [ ' <div ' , ' <b ' , ' <i ' , ' <u ' , ' <strike ' , ' <li ' , ' <blockquote ' , ' <a href ' ] :
2012-11-14 10:38:49 +00:00
self . assertIn ( tag , sanitized_html , ' html_sanitize stripped too much of original html ' )
2012-12-26 16:25:05 +00:00
for attr in [ ' javascript ' ] :
2012-11-14 10:38:49 +00:00
self . assertNotIn ( attr , sanitized_html , ' html_sanitize did not remove enough unwanted attributes ' )
2012-11-06 11:54:20 +00:00
2013-01-02 16:14:58 +00:00
emails = [ ( " Charles <charles.bidule@truc.fr> " , " Charles <charles.bidule@truc.fr> " ) ,
2013-01-02 16:25:44 +00:00
( " Dupuis < ' tr/-: $ { dupuis#$ ' @truc.baz.fr> " , " Dupuis < ' tr/-: $ { dupuis#$ ' @truc.baz.fr> " ) ,
2013-01-02 16:14:58 +00:00
( " Technical <service/technical+2@open.com> " , " Technical <service/technical+2@open.com> " ) ,
( " Div nico <div-nico@open.com> " , " Div nico <div-nico@open.com> " ) ]
2012-12-31 15:44:51 +00:00
for email in emails :
2013-01-02 16:14:58 +00:00
self . assertIn ( email [ 1 ] , html_sanitize ( email [ 0 ] ) , ' html_sanitize stripped emails of original html ' )
2012-12-31 15:44:51 +00:00
2012-12-26 16:25:05 +00:00
def test_edi_source ( self ) :
html = html_sanitize ( EDI_LIKE_HTML_SOURCE )
self . assertIn ( ' div style= " font-family: \' Lucica Grande \' , Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: #FFF; ' , html ,
' html_sanitize removed valid style attribute ' )
self . assertIn ( ' <span style= " color: #222; margin-bottom: 5px; display: block; " > ' , html ,
' html_sanitize removed valid style attribute ' )
self . assertIn ( ' img class= " oe_edi_paypal_button " src= " https://www.paypal.com/en_US/i/btn/btn_paynowCC_LG.gif " ' , html ,
' html_sanitize removed valid img ' )
self . assertNotIn ( ' </body></html> ' , html , ' html_sanitize did not remove extra closing tags ' )
2012-08-13 14:22:32 +00:00
2012-11-06 11:54:20 +00:00
2012-11-06 12:18:24 +00:00
class TestCleaner ( unittest2 . TestCase ) :
2012-11-14 10:38:49 +00:00
""" Test the email cleaner function that filters the content of incoming emails """
2012-11-09 12:35:21 +00:00
def test_html_email_clean ( self ) :
# Test1: reply through gmail: quote in blockquote, signature --\nAdministrator
new_html = html_email_clean ( GMAIL_REPLY1_SAN )
self . assertNotIn ( ' blockquote ' , new_html , ' html_email_cleaner did not remove a blockquote ' )
self . assertNotIn ( ' I contact you about our meeting ' , new_html , ' html_email_cleaner wrongly removed the quoted content ' )
self . assertNotIn ( ' Administrator ' , new_html , ' html_email_cleaner did not erase the signature ' )
self . assertIn ( ' Ok for me ' , new_html , ' html_email_cleaner erased too much content ' )
# Test2: reply through Tunderbird 16.0.2
new_html = html_email_clean ( THUNDERBIRD_16_REPLY1_SAN )
self . assertNotIn ( ' blockquote ' , new_html , ' html_email_cleaner did not remove a blockquote ' )
self . assertNotIn ( ' I contact you about our meeting ' , new_html , ' html_email_cleaner wrongly removed the quoted content ' )
self . assertNotIn ( ' Administrator ' , new_html , ' html_email_cleaner did not erase the signature ' )
self . assertNotIn ( ' Grosbedonn ' , new_html , ' html_email_cleaner did not erase the signature ' )
self . assertIn ( ' Ok for me ' , new_html , ' html_email_cleaner erased too much content ' )
# Test3: text email
new_html = html_email_clean ( TEXT_MAIL1 )
self . assertIn ( ' I contact you about our meeting ' , new_html , ' html_email_cleaner wrongly removed the quoted content ' )
self . assertNotIn ( ' Administrator ' , new_html , ' html_email_cleaner did not erase the signature ' )
# Test4: more complex text email
new_html = html_email_clean ( TEXT_TPL )
self . assertNotIn ( ' quote ' , new_html , ' html_email_cleaner did not remove correctly plaintext quotes ' )
2012-11-06 11:54:20 +00:00
2012-11-19 15:17:39 +00:00
# Test5: False boolean for text must return empty string
new_html = html_email_clean ( False )
2012-11-20 13:40:01 +00:00
self . assertEqual ( new_html , False , ' html_email_cleaner did change a False in an other value. ' )
2012-11-06 11:54:20 +00:00
2012-12-19 11:18:53 +00:00
# Test6: Message with xml and doctype tags don't crash
2012-12-19 14:39:12 +00:00
new_html = html_email_clean ( u ' <?xml version= " 1.0 " encoding= " iso-8859-1 " ?> \n <!DOCTYPE html PUBLIC " -//W3C//DTD XHTML 1.0 Transitional//EN " \n " http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd " > \n <html xmlns= " http://www.w3.org/1999/xhtml " xml:lang= " en " lang= " en " > \n <head> \n <title>404 - Not Found</title> \n </head> \n <body> \n <h1>404 - Not Found</h1> \n </body> \n </html> \n ' )
self . assertNotIn ( ' encoding ' , new_html , ' html_email_cleaner did not remove correctly encoding attributes ' )
2012-12-19 11:18:53 +00:00
2012-12-26 16:25:05 +00:00
2012-11-14 10:38:49 +00:00
class TestHtmlTools ( unittest2 . TestCase ) :
2012-11-09 12:35:21 +00:00
""" Test some of our generic utility functions about html """
2012-11-07 16:41:17 +00:00
2012-11-09 12:35:21 +00:00
def test_plaintext2html ( self ) :
2012-11-07 16:41:17 +00:00
cases = [
( " First \n Second \n Third \n \n Paragraph \n \r -- \n Signature paragraph " , ' div ' ,
" <div><p>First <br/>Second <br/>Third</p><p>Paragraph</p><p>--<br/>Signature paragraph</p></div> " ) ,
2012-11-09 12:35:21 +00:00
( " First<p>It should be escaped</p> \n Signature " , False ,
" <p>First<p>It should be escaped</p><br/>Signature</p> " )
2012-11-07 16:41:17 +00:00
]
for content , container_tag , expected in cases :
2012-11-09 12:35:21 +00:00
html = plaintext2html ( content , container_tag )
2012-11-14 13:51:59 +00:00
self . assertEqual ( html , expected , ' plaintext2html is broken ' )
2012-11-07 16:41:17 +00:00
2012-11-09 12:35:21 +00:00
def test_append_to_html ( self ) :
test_samples = [
( ' <!DOCTYPE...><HTML encoding= " blah " >some <b>content</b></HtMl> ' , ' -- \n Yours truly ' , True , True , False ,
' <!DOCTYPE...><html encoding= " blah " >some <b>content</b> \n <pre>-- \n Yours truly</pre> \n </html> ' ) ,
( ' <!DOCTYPE...><HTML encoding= " blah " >some <b>content</b></HtMl> ' , ' -- \n Yours truly ' , True , False , False ,
' <!DOCTYPE...><html encoding= " blah " >some <b>content</b> \n <p>--<br/>Yours truly</p> \n </html> ' ) ,
( ' <html><body>some <b>content</b></body></html> ' , ' <!DOCTYPE...> \n <html><body> \n <p>--</p> \n <p>Yours truly</p> \n </body> \n </html> ' , False , False , False ,
' <html><body>some <b>content</b> \n \n \n <p>--</p> \n <p>Yours truly</p> \n \n \n </body></html> ' ) ,
]
for html , content , plaintext_flag , preserve_flag , container_tag , expected in test_samples :
self . assertEqual ( append_content_to_html ( html , content , plaintext_flag , preserve_flag , container_tag ) , expected , ' append_content_to_html is broken ' )
2012-11-07 16:41:17 +00:00
2012-08-13 14:22:32 +00:00
if __name__ == ' __main__ ' :
2012-11-06 12:18:24 +00:00
unittest2 . main ( )