0
0
mirror of https://github.com/ezyang/htmlpurifier.git synced 2024-12-22 16:31:53 +00:00

Refactor unit tests to have one logical assertion per method.

- Support executing a single unit tests using __only prefix
- Hook in Email classes to main code, even if they're unused


git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/trunk@1373 48356398-32a2-884e-a903-53898d9a118a
This commit is contained in:
Edward Z. Yang 2007-08-06 06:22:23 +00:00
parent d51d3c127b
commit 3af6457801
26 changed files with 471 additions and 693 deletions

View File

@ -6,6 +6,7 @@ require_once 'HTMLPurifier/URIScheme.php';
require_once 'HTMLPurifier/URISchemeRegistry.php';
require_once 'HTMLPurifier/AttrDef/URI/Host.php';
require_once 'HTMLPurifier/PercentEncoder.php';
require_once 'HTMLPurifier/AttrDef/URI/Email.php';
// special case filtering directives

View File

@ -1,6 +1,7 @@
<?php
require_once 'HTMLPurifier/AttrDef.php';
require_once 'HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php';
class HTMLPurifier_AttrDef_URI_Email extends HTMLPurifier_AttrDef
{

View File

@ -11,18 +11,19 @@ class HTMLPurifier_AttrTransform_BdoDirTest extends HTMLPurifier_AttrTransformHa
$this->obj = new HTMLPurifier_AttrTransform_BdoDir();
}
function test() {
function testAddDefaultDir() {
$this->assertResult( array(), array('dir' => 'ltr') );
// leave existing dir alone
}
function testPreserveExistingDir() {
$this->assertResult( array('dir' => 'rtl') );
// use a different default
}
function testAlternateDefault() {
$this->config->set('Attr', 'DefaultTextDir', 'rtl');
$this->assertResult(
array(),
array('dir' => 'rtl'),
array('Attr.DefaultTextDir' => 'rtl')
array('dir' => 'rtl')
);
}

View File

@ -3,6 +3,10 @@
require_once 'HTMLPurifier/AttrTransform/BgColor.php';
require_once 'HTMLPurifier/AttrTransformHarness.php';
// we currently rely on the CSS validator to fix any problems.
// This means that this transform, strictly speaking, supports
// a superset of the functionality.
class HTMLPurifier_AttrTransform_BgColorTest extends HTMLPurifier_AttrTransformHarness
{
@ -11,31 +15,31 @@ class HTMLPurifier_AttrTransform_BgColorTest extends HTMLPurifier_AttrTransformH
$this->obj = new HTMLPurifier_AttrTransform_BgColor();
}
function test() {
function testEmptyInput() {
$this->assertResult( array() );
// we currently rely on the CSS validator to fix any problems.
// This means that this transform, strictly speaking, supports
// a superset of the functionality.
}
function testBasicTransform() {
$this->assertResult(
array('bgcolor' => '#000000'),
array('style' => 'background-color:#000000;')
);
}
function testPrependNewCSS() {
$this->assertResult(
array('bgcolor' => '#000000', 'style' => 'font-weight:bold'),
array('style' => 'background-color:#000000;font-weight:bold')
);
}
function testLenientTreatmentOfInvalidInput() {
// this may change when we natively support the datatype and
// validate its contents before forwarding it on
$this->assertResult(
array('bgcolor' => '#F00'),
array('style' => 'background-color:#F00;')
);
}
}

View File

@ -11,27 +11,29 @@ class HTMLPurifier_AttrTransform_BoolToCSSTest extends HTMLPurifier_AttrTransfor
$this->obj = new HTMLPurifier_AttrTransform_BoolToCSS('foo', 'bar:3in;');
}
function test() {
function testEmptyInput() {
$this->assertResult( array() );
}
function testBasicTransform() {
$this->assertResult(
array('foo' => 'foo'),
array('style' => 'bar:3in;')
);
// boolean attribute just has to be set: we don't care about
// anything else
}
function testIgnoreValueOfBooleanAttribute() {
$this->assertResult(
array('foo' => 'no'),
array('style' => 'bar:3in;')
);
}
function testPrependCSS() {
$this->assertResult(
array('foo' => 'foo', 'style' => 'background-color:#F00;'),
array('style' => 'bar:3in;background-color:#F00;')
);
}
}

View File

@ -12,27 +12,29 @@ class HTMLPurifier_AttrTransform_BorderTest extends HTMLPurifier_AttrTransformHa
$this->obj = new HTMLPurifier_AttrTransform_Border();
}
function test() {
function testEmptyInput() {
$this->assertResult( array() );
}
function testBasicTransform() {
$this->assertResult(
array('border' => '1'),
array('style' => 'border:1px solid;')
);
// once again, no validation done here, we expect CSS validator
// to catch it
}
function testLenientTreatmentOfInvalidInput() {
$this->assertResult(
array('border' => '10%'),
array('style' => 'border:10%px solid;')
);
}
function testPrependNewCSS() {
$this->assertResult(
array('border' => '23', 'style' => 'font-weight:bold;'),
array('style' => 'border:23px solid;font-weight:bold;')
);
}
}

View File

@ -6,38 +6,44 @@ require_once 'HTMLPurifier/AttrTransformHarness.php';
class HTMLPurifier_AttrTransform_EnumToCSSTest extends HTMLPurifier_AttrTransformHarness
{
function testRegular() {
function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_AttrTransform_EnumToCSS('align', array(
'left' => 'text-align:left;',
'right' => 'text-align:right;'
));
// leave empty arrays alone
}
function testEmptyInput() {
$this->assertResult( array() );
// leave arrays without interesting stuff alone
}
function testPreserveArraysWithoutInterestingAttributes() {
$this->assertResult( array('style' => 'font-weight:bold;') );
// test each of the conversions
}
function testConvertAlignLeft() {
$this->assertResult(
array('align' => 'left'),
array('style' => 'text-align:left;')
);
}
function testConvertAlignRight() {
$this->assertResult(
array('align' => 'right'),
array('style' => 'text-align:right;')
);
// drop garbage value
}
function testRemoveInvalidAlign() {
$this->assertResult(
array('align' => 'invalid'),
array()
);
// test CSS munging
}
function testPrependNewCSS() {
$this->assertResult(
array('align' => 'left', 'style' => 'font-weight:bold;'),
array('style' => 'text-align:left;font-weight:bold;')
@ -46,31 +52,23 @@ class HTMLPurifier_AttrTransform_EnumToCSSTest extends HTMLPurifier_AttrTransfor
}
function testCaseInsensitive() {
$this->obj = new HTMLPurifier_AttrTransform_EnumToCSS('align', array(
'right' => 'text-align:right;'
));
// test case insensitivity
$this->assertResult(
array('align' => 'RIGHT'),
array('style' => 'text-align:right;')
);
}
function testCaseSensitive() {
$this->obj = new HTMLPurifier_AttrTransform_EnumToCSS('align', array(
'right' => 'text-align:right;'
), true);
// test case insensitivity
$this->assertResult(
array('align' => 'RIGHT'),
array()
);
}
}

View File

@ -11,39 +11,37 @@ class HTMLPurifier_AttrTransform_ImgRequiredTest extends HTMLPurifier_AttrTransf
$this->obj = new HTMLPurifier_AttrTransform_ImgRequired();
}
function test() {
function testAddMissingAttr() {
$this->config->set('Core', 'RemoveInvalidImg', false);
$this->assertResult(
array(),
array('src' => '', 'alt' => 'Invalid image'),
array(
'Core.RemoveInvalidImg' => false
)
array('src' => '', 'alt' => 'Invalid image')
);
}
function testAlternateDefaults() {
$this->config->set('Attr', 'DefaultInvalidImage', 'blank.png');
$this->config->set('Attr', 'DefaultInvalidImageAlt', 'Pawned!');
$this->config->set('Core', 'RemoveInvalidImg', false);
$this->assertResult(
array(),
array('src' => 'blank.png', 'alt' => 'Pawned!'),
array(
'Attr.DefaultInvalidImage' => 'blank.png',
'Attr.DefaultInvalidImageAlt' => 'Pawned!',
'Core.RemoveInvalidImg' => false
)
array('src' => 'blank.png', 'alt' => 'Pawned!')
);
}
function testGenerateAlt() {
$this->assertResult(
array('src' => '/path/to/foobar.png'),
array('src' => '/path/to/foobar.png', 'alt' => 'foobar.png')
);
}
function testAddDefaultSrc() {
$this->config->set('Core', 'RemoveInvalidImg', false);
$this->assertResult(
array('alt' => 'intrigue'),
array('alt' => 'intrigue', 'src' => ''),
array(
'Core.RemoveInvalidImg' => false
)
array('alt' => 'intrigue', 'src' => '')
);
}
}

View File

@ -9,33 +9,35 @@ class HTMLPurifier_AttrTransform_ImgSpaceTest extends HTMLPurifier_AttrTransform
function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_AttrTransform_ImgSpace('vspace');
}
function testVertical() {
$this->obj = new HTMLPurifier_AttrTransform_ImgSpace('vspace');
function testEmptyInput() {
$this->assertResult( array() );
}
function testVerticalBasicUsage() {
$this->assertResult(
array('vspace' => '1'),
array('style' => 'margin-top:1px;margin-bottom:1px;')
);
// no validation done here, we expect CSS validator to catch it
}
function testLenientHandlingOfInvalidInput() {
$this->assertResult(
array('vspace' => '10%'),
array('style' => 'margin-top:10%px;margin-bottom:10%px;')
);
}
function testPrependNewCSS() {
$this->assertResult(
array('vspace' => '23', 'style' => 'font-weight:bold;'),
array('style' => 'margin-top:23px;margin-bottom:23px;font-weight:bold;')
);
}
function testHorizontal() {
function testHorizontalBasicUsage() {
$this->obj = new HTMLPurifier_AttrTransform_ImgSpace('hspace');
$this->assertResult(
array('hspace' => '1'),
@ -43,7 +45,7 @@ class HTMLPurifier_AttrTransform_ImgSpaceTest extends HTMLPurifier_AttrTransform
);
}
function testInvalid() {
function testInvalidConstructionParameter() {
$this->expectError('ispace is not valid space attribute');
$this->obj = new HTMLPurifier_AttrTransform_ImgSpace('ispace');
$this->assertResult(

View File

@ -13,35 +13,36 @@ class HTMLPurifier_AttrTransform_LangTest
$this->obj = new HTMLPurifier_AttrTransform_Lang();
}
function test() {
// leave non-lang'ed elements alone
$this->assertResult(array(), true);
// copy lang to xml:lang
function testEmptyInput() {
$this->assertResult(array());
}
function testCopyLangToXMLLang() {
$this->assertResult(
array('lang' => 'en'),
array('lang' => 'en', 'xml:lang' => 'en')
);
// preserve attributes
}
function testPreserveAttributes() {
$this->assertResult(
array('src' => 'vert.png', 'lang' => 'fr'),
array('src' => 'vert.png', 'lang' => 'fr', 'xml:lang' => 'fr')
);
// copy xml:lang to lang
}
function testCopyXMLLangToLang() {
$this->assertResult(
array('xml:lang' => 'en'),
array('xml:lang' => 'en', 'lang' => 'en')
);
// both set, override lang with xml:lang
}
function testXMLLangOverridesLang() {
$this->assertResult(
array('lang' => 'fr', 'xml:lang' => 'de'),
array('lang' => 'de', 'xml:lang' => 'de')
);
}
}

View File

@ -11,21 +11,32 @@ class HTMLPurifier_AttrTransform_LengthTest extends HTMLPurifier_AttrTransformHa
$this->obj = new HTMLPurifier_AttrTransform_Length('width');
}
function test() {
function testEmptyInput() {
$this->assertResult( array() );
}
function testTransformPixel() {
$this->assertResult(
array('width' => '10'),
array('style' => 'width:10px;')
);
}
function testTransformPercentage() {
$this->assertResult(
array('width' => '10%'),
array('style' => 'width:10%;')
);
}
function testPrependNewCSS() {
$this->assertResult(
array('width' => '10%', 'style' => 'font-weight:bold'),
array('style' => 'width:10%;font-weight:bold')
);
// this behavior might change
}
function testLenientTreatmentOfInvalidInput() {
$this->assertResult(
array('width' => 'asdf'),
array('style' => 'width:asdf;')

View File

@ -11,12 +11,18 @@ class HTMLPurifier_AttrTransform_NameTest extends HTMLPurifier_AttrTransformHarn
$this->obj = new HTMLPurifier_AttrTransform_Name();
}
function test() {
function testEmpty() {
$this->assertResult( array() );
}
function testTransformNameToID() {
$this->assertResult(
array('name' => 'free'),
array('id' => 'free')
);
}
function testExistingIDOverridesName() {
$this->assertResult(
array('name' => 'tryit', 'id' => 'tobad'),
array('id' => 'tobad')

View File

@ -6,6 +6,7 @@ class HTMLPurifier_AttrTransformHarness extends HTMLPurifier_ComplexHarness
{
function setUp() {
parent::setUp();
$this->func = 'transform';
}

View File

@ -6,28 +6,36 @@ require_once 'HTMLPurifier/ChildDef/Chameleon.php';
class HTMLPurifier_ChildDef_ChameleonTest extends HTMLPurifier_ChildDefHarness
{
function test() {
var $isInline;
function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_ChildDef_Chameleon(
'b | i', // allowed only when in inline context
'b | i | div' // allowed only when in block context
);
$this->context->register('IsInline', $this->isInline);
}
function testInlineAlwaysAllowed() {
$this->isInline = true;
$this->assertResult(
'<b>Allowed.</b>', true,
array(), array('IsInline' => true)
'<b>Allowed.</b>'
);
}
function testBlockNotAllowedInInline() {
$this->isInline = true;
$this->assertResult(
'<div>Not allowed.</div>', '',
array(), array('IsInline' => true)
'<div>Not allowed.</div>', ''
);
}
function testBlockAllowedInNonInline() {
$this->isInline = false;
$this->assertResult(
'<div>Allowed.</div>', true,
array(), array('IsInline' => false)
'<div>Allowed.</div>'
);
}
}

View File

@ -6,13 +6,17 @@ require_once 'HTMLPurifier/ChildDef/Optional.php';
class HTMLPurifier_ChildDef_OptionalTest extends HTMLPurifier_ChildDefHarness
{
function test() {
function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_ChildDef_Optional('b | i');
}
function testBasicUsage() {
$this->assertResult('<b>Bold text</b><img />', '<b>Bold text</b>');
}
function testRemoveForbiddenText() {
$this->assertResult('Not allowed text', '');
}
}

View File

@ -6,8 +6,7 @@ require_once 'HTMLPurifier/ChildDef/Required.php';
class HTMLPurifier_ChildDef_RequiredTest extends HTMLPurifier_ChildDefHarness
{
function testParsing() {
function testPrepareString() {
$def = new HTMLPurifier_ChildDef_Required('foobar | bang |gizmo');
$this->assertIdentical($def->elements,
array(
@ -15,51 +14,61 @@ class HTMLPurifier_ChildDef_RequiredTest extends HTMLPurifier_ChildDefHarness
,'bang' => true
,'gizmo' => true
));
}
function testPrepareArray() {
$def = new HTMLPurifier_ChildDef_Required(array('href', 'src'));
$this->assertIdentical($def->elements,
array(
'href' => true
,'src' => true
));
}
function testPCDATAForbidden() {
function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_ChildDef_Required('dt | dd');
}
function testEmptyInput() {
$this->assertResult('', false);
}
function testRemoveIllegalTagsAndElements() {
$this->assertResult(
'<dt>Term</dt>Text in an illegal location'.
'<dd>Definition</dd><b>Illegal tag</b>',
'<dt>Term</dt><dd>Definition</dd>');
$this->assertResult('How do you do!', false);
}
function testIgnoreWhitespace() {
// whitespace shouldn't trigger it
$this->assertResult("\n<dd>Definition</dd> ");
}
function testPreserveWhitespaceAfterRemoval() {
$this->assertResult(
'<dd>Definition</dd> <b></b> ',
'<dd>Definition</dd> '
);
}
function testDeleteNodeIfOnlyWhitespace() {
$this->assertResult("\t ", false);
}
function testPCDATAAllowed() {
$this->obj = new HTMLPurifier_ChildDef_Required('#PCDATA | b');
$this->assertResult('<b>Bold text</b><img />', '<b>Bold text</b>');
// with child escaping on
$this->assertResult('Out <b>Bold text</b><img />', 'Out <b>Bold text</b>');
}
function testPCDATAAllowedWithEscaping() {
$this->obj = new HTMLPurifier_ChildDef_Required('#PCDATA | b');
$this->config->set('Core', 'EscapeInvalidChildren', true);
$this->assertResult(
'<b>Bold text</b><img />',
'<b>Bold text</b>&lt;img /&gt;',
array(
'Core.EscapeInvalidChildren' => true
)
'Out <b>Bold text</b><img />',
'Out <b>Bold text</b>&lt;img /&gt;'
);
}

View File

@ -7,48 +7,76 @@ class HTMLPurifier_ChildDef_StrictBlockquoteTest
extends HTMLPurifier_ChildDefHarness
{
function test() {
function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_ChildDef_StrictBlockquote('div | p');
// assuming default wrap is p
}
function testEmptyInput() {
$this->assertResult('');
}
function testPreserveValidP() {
$this->assertResult('<p>Valid</p>');
}
function testPreserveValidDiv() {
$this->assertResult('<div>Still valid</div>');
}
function testWrapTextWithP() {
$this->assertResult('Needs wrap', '<p>Needs wrap</p>');
}
function testNoWrapForWhitespaceOrValidElements() {
$this->assertResult('<p>Do not wrap</p> <p>Whitespace</p>');
}
function testWrapTextNextToValidElements() {
$this->assertResult(
'Wrap'. '<p>Do not wrap</p>',
'<p>Wrap</p><p>Do not wrap</p>'
);
}
function testWrapInlineElements() {
$this->assertResult(
'<p>Do not</p>'.'<b>Wrap</b>',
'<p>Do not</p><p><b>Wrap</b></p>'
);
}
function testWrapAndRemoveInvalidTags() {
$this->assertResult(
'<li>Not allowed</li>Paragraph.<p>Hmm.</p>',
'<p>Not allowedParagraph.</p><p>Hmm.</p>'
);
}
function testWrapComplicatedSring() {
$this->assertResult(
$var = 'He said<br />perhaps<br />we should <b>nuke</b> them.',
"<p>$var</p>"
);
}
function testWrapAndRemoveInvalidTagsComplex() {
$this->assertResult(
'<foo>Bar</foo><bas /><b>People</b>Conniving.'. '<p>Fools!</p>',
'<p>Bar'. '<b>People</b>Conniving.</p><p>Fools!</p>'
);
$this->assertResult('Needs wrap', '<div>Needs wrap</div>',
array('HTML.BlockWrapper' => 'div'));
}
function testAlternateWrapper() {
$this->config->set('HTML', 'BlockWrapper', 'div');
$this->assertResult('Needs wrap', '<div>Needs wrap</div>');
}
function testError() {
$this->obj = new HTMLPurifier_ChildDef_StrictBlockquote('div | p');
$this->assertResult('Needs wrap', '<p>Needs wrap</p>',
array('HTML.BlockWrapper' => 'dav'));
$this->swallowErrors();
$this->config->set('HTML', 'BlockWrapper', 'dav');
$this->assertResult('Needs wrap', '<p>Needs wrap</p>');
}
}

View File

@ -6,10 +6,12 @@ require_once 'HTMLPurifier/ChildDef/Table.php';
class HTMLPurifier_ChildDef_TableTest extends HTMLPurifier_ChildDefHarness
{
function test() {
function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_ChildDef_Table();
}
function test() {
$this->assertResult('', false);
// we're using empty tags to compact the tests: under real circumstances

View File

@ -7,6 +7,7 @@ class HTMLPurifier_ChildDefHarness extends HTMLPurifier_ComplexHarness
{
function setUp() {
parent::setUp();
$this->obj = null;
$this->func = 'validateChildren';
$this->to_tokens = true;

View File

@ -16,6 +16,7 @@ class HTMLPurifier_SimpleTest_Reporter extends HTMLReporter
?>><?php echo $file ?></option>
<?php } ?>
</select>
<input type="checkbox" name="standalone" title="Standalone version?" <?php if(isset($_GET['standalone'])) {echo 'checked="checked" ';} ?>/>
<input type="submit" value="Go">
</form>
<?php

View File

@ -11,26 +11,36 @@ class HTMLPurifier_Strategy_CoreTest extends HTMLPurifier_StrategyHarness
$this->obj = new HTMLPurifier_Strategy_Core();
}
function test() {
function testBlankInput() {
$this->assertResult('');
}
function testMakeWellFormed() {
$this->assertResult(
'<b>Make well formed.',
'<b>Make well formed.</b>'
);
}
function testFixNesting() {
$this->assertResult(
'<b><div>Fix nesting.</div></b>',
'<b></b><div>Fix nesting.</div>'
);
}
function testRemoveForeignElements() {
$this->assertResult(
'<asdf>Foreign element removal.</asdf>',
'Foreign element removal.'
);
}
function testFirstThree() {
$this->assertResult(
'<foo><b><div>All three.</div></b>',
'<b></b><div>All three.</div>'
);
}
}

View File

@ -11,79 +11,81 @@ class HTMLPurifier_Strategy_FixNestingTest extends HTMLPurifier_StrategyHarness
$this->obj = new HTMLPurifier_Strategy_FixNesting();
}
function testBlockAndInlineIntegration() {
// legal inline
function testPreserveInlineInRoot() {
$this->assertResult('<b>Bold text</b>');
// legal inline and block (default parent element is FLOW)
}
function testPreserveInlineAndBlockInRoot() {
$this->assertResult('<a href="about:blank">Blank</a><div>Block</div>');
// illegal block in inline
}
function testRemoveBlockInInline() {
$this->assertResult(
'<b><div>Illegal div.</div></b>',
'<b>Illegal div.</b>'
);
// same test with different configuration (fragile)
$this->assertResult(
'<b><div>Illegal div.</div></b>',
'<b>&lt;div&gt;Illegal div.&lt;/div&gt;</b>',
array('Core.EscapeInvalidChildren' => true)
);
}
function testNodeRemovalIntegration() {
// test of empty set that's required, resulting in removal of node
function testEscapeBlockInInline() {
$this->config->set('Core', 'EscapeInvalidChildren', true);
$this->assertResult(
'<b><div>Illegal div.</div></b>',
'<b>&lt;div&gt;Illegal div.&lt;/div&gt;</b>'
);
}
function testRemoveNodeWithMissingRequiredElements() {
$this->assertResult('<ul></ul>', '');
// test illegal text which gets removed
}
function testRemoveIllegalPCDATA() {
$this->assertResult(
'<ul>Illegal text<li>Legal item</li></ul>',
'<ul><li>Legal item</li></ul>'
);
}
function testTableIntegration() {
// test custom table definition
$this->assertResult(
'<table><tr><td>Cell 1</td></tr></table>'
);
function testCustomTableDefinition() {
$this->assertResult('<table><tr><td>Cell 1</td></tr></table>');
}
function testRemoveEmptyTable() {
$this->assertResult('<table></table>', '');
}
function testChameleonIntegration() {
// block in inline ins not allowed
function testChameleonRemoveBlockInNodeInInline() {
$this->assertResult(
'<span><ins><div>Not allowed!</div></ins></span>',
'<span><ins>Not allowed!</ins></span>'
);
// test block element that has inline content
}
function testChameleonRemoveBlockInBlockNodeWithInlineContent() {
$this->assertResult(
'<h1><ins><div>Not allowed!</div></ins></h1>',
'<h1><ins>Not allowed!</ins></h1>'
);
// stacked ins/del
}
function testNestedChameleonRemoveBlockInNodeWithInlineContent() {
$this->assertResult(
'<h1><ins><del><div>Not allowed!</div></del></ins></h1>',
'<h1><ins><del>Not allowed!</del></ins></h1>'
);
}
function testNestedChameleonPreserveBlockInBlock() {
$this->assertResult(
'<div><ins><del><div>Allowed!</div></del></ins></div>'
);
}
function testChameleonEscapeInvalidBlockInInline() {
$this->config->set('Core', 'EscapeInvalidChildren', true);
$this->assertResult( // alt config
'<span><ins><div>Not allowed!</div></ins></span>',
'<span><ins>&lt;div&gt;Not allowed!&lt;/div&gt;</ins></span>',
array('Core.EscapeInvalidChildren' => true)
'<span><ins>&lt;div&gt;Not allowed!&lt;/div&gt;</ins></span>'
);
}
function testExclusionsIntegration() {
@ -93,41 +95,37 @@ class HTMLPurifier_Strategy_FixNestingTest extends HTMLPurifier_StrategyHarness
'<a><span></span></a>'
);
}
function testCustomParentIntegration() {
// test inline parent
$this->assertResult(
'<b>Bold</b>', true, array('HTML.Parent' => 'span')
);
$this->assertResult(
'<div>Reject</div>', 'Reject', array('HTML.Parent' => 'span')
);
}
function testError() {
// test fallback to div
$this->expectError('Cannot use unrecognized element as parent.');
$this->assertResult(
'<div>Accept</div>', true, array('HTML.Parent' => 'obviously-impossible')
);
$this->swallowErrors();
function testPreserveInlineNodeInInlineRootNode() {
$this->config->set('HTML', 'Parent', 'span');
$this->assertResult('<b>Bold</b>');
}
function testDoubleCheckIntegration() {
// breaks without the redundant checking code
function testRemoveBlockNodeInInlineRootNode() {
$this->config->set('HTML', 'Parent', 'span');
$this->assertResult('<div>Reject</div>', 'Reject');
}
function testInvalidParentError() {
// test fallback to div
$this->config->set('HTML', 'Parent', 'obviously-impossible');
$this->expectError('Cannot use unrecognized element as parent.');
$this->assertResult('<div>Accept</div>');
}
function testCascadingRemovalOfNodesMissingRequiredChildren() {
$this->assertResult('<table><tr></tr></table>', '');
// special case, prevents scrolling one back to find parent
}
function testCascadingRemovalSpecialCaseCannotScrollOneBack() {
$this->assertResult('<table><tr></tr><tr></tr></table>', '');
// cascading rollbacks
$this->assertResult(
'<table><tbody><tr></tr><tr></tr></tbody><tr></tr><tr></tr></table>',
''
);
// rollbacks twice
}
function testLotsOfCascadingRemovalOfNodes() {
$this->assertResult('<table><tbody><tr></tr><tr></tr></tbody><tr></tr><tr></tr></table>', '');
}
function testAdjacentRemovalOfNodeMissingRequiredChildren() {
$this->assertResult('<table></table><table></table>', '');
}

View File

@ -9,113 +9,77 @@ class HTMLPurifier_Strategy_MakeWellFormedTest extends HTMLPurifier_StrategyHarn
function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_Strategy_MakeWellFormed();
$this->config = array();
}
function testNormalIntegration() {
function testEmptyInput() {
$this->assertResult('');
}
function testWellFormedInput() {
$this->assertResult('This is <b>bold text</b>.');
}
function testUnclosedTagIntegration() {
function testUnclosedTagTerminatedByDocumentEnd() {
$this->assertResult(
'<b>Unclosed tag, gasp!',
'<b>Unclosed tag, gasp!</b>'
);
}
function testUnclosedTagTerminatedByParentNodeEnd() {
$this->assertResult(
'<b><i>Bold and italic?</b>',
'<b><i>Bold and italic?</i></b>'
);
}
function testRemoveStrayClosingTag() {
$this->assertResult(
'Unused end tags... recycle!</b>',
'Unused end tags... recycle!'
);
}
function testEmptyTagDetectionIntegration() {
function testConvertStartToEmpty() {
$this->assertResult(
'<br style="clear:both;">',
'<br style="clear:both;" />'
);
}
function testConvertEmptyToStart() {
$this->assertResult(
'<div style="clear:both;" />',
'<div style="clear:both;"></div>'
);
}
function testAutoClose() {
// paragraph
function testAutoCloseParagraph() {
$this->assertResult(
'<p>Paragraph 1<p>Paragraph 2',
'<p>Paragraph 1</p><p>Paragraph 2</p>'
);
}
function testAutoCloseParagraphInsideDiv() {
$this->assertResult(
'<div><p>Paragraphs<p>In<p>A<p>Div</div>',
'<div><p>Paragraphs</p><p>In</p><p>A</p><p>Div</p></div>'
);
// list
}
function testAutoCloseListItem() {
$this->assertResult(
'<ol><li>Item 1<li>Item 2</ol>',
'<ol><li>Item 1</li><li>Item 2</li></ol>'
);
// colgroup
}
function testAutoCloseColgroup() {
$this->assertResult(
'<table><colgroup><col /><tr></tr></table>',
'<table><colgroup><col /></colgroup><tr></tr></table>'
);
}
function testMultipleInjectors() {
$this->config = array('AutoFormat.AutoParagraph' => true, 'AutoFormat.Linkify' => true);
$this->assertResult(
'Foobar',
'<p>Foobar</p>'
);
$this->assertResult(
'http://example.com',
'<p><a href="http://example.com">http://example.com</a></p>'
);
$this->assertResult(
'<b>http://example.com</b>',
'<p><b><a href="http://example.com">http://example.com</a></b></p>'
);
$this->assertResult(
'<b>http://example.com',
'<p><b><a href="http://example.com">http://example.com</a></b></p>'
);
$this->assertResult(
'http://example.com
http://dev.example.com',
'<p><a href="http://example.com">http://example.com</a></p><p><a href="http://dev.example.com">http://dev.example.com</a></p>'
);
$this->assertResult(
'http://example.com <div>http://example.com</div>',
'<p><a href="http://example.com">http://example.com</a> </p><div><a href="http://example.com">http://example.com</a></div>'
);
$this->assertResult(
'This URL http://example.com is what you need',
'<p>This URL <a href="http://example.com">http://example.com</a> is what you need</p>'
);
}
}

View File

@ -3,8 +3,7 @@
require_once 'HTMLPurifier/StrategyHarness.php';
require_once 'HTMLPurifier/Strategy/RemoveForeignElements.php';
class HTMLPurifier_Strategy_RemoveForeignElementsTest
extends HTMLPurifier_StrategyHarness
class HTMLPurifier_Strategy_RemoveForeignElementsTest extends HTMLPurifier_StrategyHarness
{
function setUp() {
@ -12,96 +11,75 @@ class HTMLPurifier_Strategy_RemoveForeignElementsTest
$this->obj = new HTMLPurifier_Strategy_RemoveForeignElements();
}
function test() {
$this->config = array('HTML.Doctype' => 'XHTML 1.0 Strict');
function testBlankInput() {
$this->assertResult('');
}
function testPreserveRecognizedElements() {
$this->assertResult('This is <b>bold text</b>.');
}
function testRemoveForeignElements() {
$this->assertResult(
'<asdf>Bling</asdf><d href="bang">Bong</d><foobar />',
'BlingBong'
);
}
function testRemoveScriptAndContents() {
$this->assertResult(
'<script>alert();</script>',
''
);
}
function testRemoveStyleAndContents() {
$this->assertResult(
'<style>.foo {blink;}</style>',
''
);
}
function testRemoveOnlyScriptTagsLegacy() {
$this->config->set('Core', 'RemoveScriptContents', false);
$this->assertResult(
'<script>alert();</script>',
'alert();',
array('Core.RemoveScriptContents' => false)
'alert();'
);
}
function testRemoveOnlyScriptTags() {
$this->config->set('Core', 'HiddenElements', array());
$this->assertResult(
'<script>alert();</script>',
'alert();',
array('Core.HiddenElements' => array())
'alert();'
);
$this->assertResult(
'<menu><li>Item 1</li></menu>',
'<ul><li>Item 1</li></ul>'
);
// test center transform
$this->assertResult(
'<center>Look I am Centered!</center>',
'<div style="text-align:center;">Look I am Centered!</div>'
);
// test font transform
$this->assertResult(
'<font color="red" face="Arial" size="6">Big Warning!</font>',
'<span style="color:red;font-family:Arial;font-size:xx-large;">Big'.
' Warning!</span>'
);
// test removal of invalid img tag
$this->assertResult(
'<img />',
''
);
// test preservation of valid img tag
}
function testRemoveInvalidImg() {
$this->assertResult('<img />', '');
}
function testPreserveValidImg() {
$this->assertResult('<img src="foobar.gif" alt="foobar.gif" />');
// test preservation of invalid img tag when removal is disabled
$this->assertResult(
'<img />',
true,
array(
'Core.RemoveInvalidImg' => false
)
);
// test transform to unallowed element
$this->assertResult(
'<font color="red" face="Arial" size="6">Big Warning!</font>',
'Big Warning!',
array('HTML.Allowed' => 'div')
);
// text-ify commented script contents ( the trailing comment gets
// removed during generation )
}
function testPreserveInvalidImgWhenRemovalIsDisabled() {
$this->config->set('Core', 'RemoveInvalidImg', false);
$this->assertResult('<img />');
}
function testTextifyCommentedScriptContents() {
$this->config->set('HTML', 'Trusted', true);
$this->config->set('Output', 'CommentScriptContents', false); // simplify output
$this->assertResult(
'<script type="text/javascript"><!--
alert(<b>bold</b>);
// --></script>',
'<script type="text/javascript">
alert(&lt;b&gt;bold&lt;/b&gt;);
// </script>',
array('HTML.Trusted' => true, 'Output.CommentScriptContents' => false)
// </script>'
);
}
}

View File

@ -1,6 +1,5 @@
<?php
require_once('HTMLPurifier/Config.php');
require_once('HTMLPurifier/StrategyHarness.php');
require_once('HTMLPurifier/Strategy/ValidateAttributes.php');
@ -11,126 +10,99 @@ class HTMLPurifier_Strategy_ValidateAttributesTest extends
function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_Strategy_ValidateAttributes();
$this->config = array('HTML.Doctype' => 'XHTML 1.0 Strict');
}
function testEmpty() {
function testEmptyInput() {
$this->assertResult('');
}
function testIDs() {
function testRemoveIDByDefault() {
$this->assertResult(
'<div id="valid">Kill the ID.</div>',
'<div>Kill the ID.</div>'
);
$this->assertResult('<div id="valid">Preserve the ID.</div>', true,
array('HTML.EnableAttrID' => true));
$this->assertResult(
'<div id="0invalid">Kill the ID.</div>',
'<div>Kill the ID.</div>',
array('HTML.EnableAttrID' => true)
);
// test id accumulator
$this->assertResult(
'<div id="valid">Valid</div><div id="valid">Invalid</div>',
'<div id="valid">Valid</div><div>Invalid</div>',
array('HTML.EnableAttrID' => true)
);
}
function testRemoveInvalidDir() {
$this->assertResult(
'<span dir="up-to-down">Bad dir.</span>',
'<span>Bad dir.</span>'
);
// test attribute key case sensitivity
$this->assertResult(
'<div ID="valid">Convert ID to lowercase.</div>',
'<div id="valid">Convert ID to lowercase.</div>',
array('HTML.EnableAttrID' => true)
);
// test simple attribute substitution
$this->assertResult(
'<div id=" valid ">Trim whitespace.</div>',
'<div id="valid">Trim whitespace.</div>',
array('HTML.EnableAttrID' => true)
);
// test configuration id blacklist
$this->assertResult(
'<div id="invalid">Invalid</div>',
'<div>Invalid</div>',
array(
'Attr.IDBlacklist' => array('invalid'),
'HTML.EnableAttrID' => true
)
);
// name rewritten as id
$this->assertResult(
'<a name="foobar" />',
'<a id="foobar" />',
array('HTML.EnableAttrID' => true)
);
}
function testClasses() {
function testPreserveValidClass() {
$this->assertResult('<div class="valid">Valid</div>');
}
function testSelectivelyRemoveInvalidClasses() {
$this->assertResult(
'<div class="valid 0invalid">Keep valid.</div>',
'<div class="valid">Keep valid.</div>'
);
}
function testTitle() {
function testPreserveTitle() {
$this->assertResult(
'<acronym title="PHP: Hypertext Preprocessor">PHP</acronym>'
);
}
function testLang() {
function testAddXMLLang() {
$this->assertResult(
'<span lang="fr">La soupe.</span>',
'<span lang="fr" xml:lang="fr">La soupe.</span>'
);
// test only xml:lang for XHTML 1.1
}
function testOnlyXMLLangInXHTML11() {
$this->config->set('HTML', 'Doctype', 'XHTML 1.1');
$this->assertResult(
'<b lang="en">asdf</b>',
'<b xml:lang="en">asdf</b>', array('HTML.Doctype' => 'XHTML 1.1')
'<b xml:lang="en">asdf</b>'
);
}
function testAlign() {
$this->assertResult(
'<h1 align="center">Centered Headline</h1>',
'<h1 style="text-align:center;">Centered Headline</h1>'
);
$this->assertResult(
'<h1 align="right">Right-aligned Headline</h1>',
'<h1 style="text-align:right;">Right-aligned Headline</h1>'
);
$this->assertResult(
'<h1 align="left">Left-aligned Headline</h1>',
'<h1 style="text-align:left;">Left-aligned Headline</h1>'
);
$this->assertResult(
'<p align="justify">Justified Paragraph</p>',
'<p style="text-align:justify;">Justified Paragraph</p>'
);
$this->assertResult(
'<h1 align="invalid">Invalid Headline</h1>',
'<h1>Invalid Headline</h1>'
);
function testBasicURI() {
$this->assertResult('<a href="http://www.google.com/">Google</a>');
}
function testTable() {
function testInvalidURI() {
$this->assertResult(
'<a href="javascript:badstuff();">Google</a>',
'<a>Google</a>'
);
}
function testBdoAddMissingDir() {
$this->assertResult(
'<bdo>Go left.</bdo>',
'<bdo dir="ltr">Go left.</bdo>'
);
}
function testBdoReplaceInvalidDirWithDefault() {
$this->assertResult(
'<bdo dir="blahblah">Invalid value!</bdo>',
'<bdo dir="ltr">Invalid value!</bdo>'
);
}
function testBdoAlternateDefaultDir() {
$this->config->set('Attr', 'DefaultTextDir', 'rtl');
$this->assertResult(
'<bdo>Go right.</bdo>',
'<bdo dir="rtl">Go right.</bdo>'
);
}
function testRemoveDirWhenNotRequired() {
$this->assertResult(
'<span dir="blahblah">Invalid value!</span>',
'<span>Invalid value!</span>'
);
}
function testTableAttributes() {
$this->assertResult(
'<table frame="above" rules="rows" summary="A test table" border="2" cellpadding="5%" cellspacing="3" width="100%">
<col align="right" width="4*" />
@ -148,293 +120,64 @@ class HTMLPurifier_Strategy_ValidateAttributesTest extends
</tr>
</table>'
);
// test col.span is non-zero
}
function testColSpanIsNonZero() {
$this->assertResult(
'<col span="0" />',
'<col />'
);
// lengths
$this->assertResult(
'<td width="5%" height="10" /><th width="10" height="5%" /><hr width="10" height="10" />',
'<td style="width:5%;height:10px;" /><th style="width:10px;height:5%;" /><hr style="width:10px;" />'
);
// td boolean transformation
$this->assertResult(
'<td nowrap />',
'<td style="white-space:nowrap;" />'
);
// caption align transformation
$this->assertResult(
'<caption align="left" />',
'<caption style="text-align:left;" />'
);
$this->assertResult(
'<caption align="right" />',
'<caption style="text-align:right;" />'
);
$this->assertResult(
'<caption align="top" />',
'<caption style="caption-side:top;" />'
);
$this->assertResult(
'<caption align="bottom" />',
'<caption style="caption-side:bottom;" />'
);
$this->assertResult(
'<caption align="nonsense" />',
'<caption />'
);
// align transformation
$this->assertResult(
'<table align="left" />',
'<table style="float:left;" />'
);
$this->assertResult(
'<table align="center" />',
'<table style="margin-left:auto;margin-right:auto;" />'
);
$this->assertResult(
'<table align="right" />',
'<table style="float:right;" />'
);
$this->assertResult(
'<table align="top" />',
'<table />'
);
}
function testURI() {
$this->assertResult('<a href="http://www.google.com/">Google</a>');
// test invalid URI
$this->assertResult(
'<a href="javascript:badstuff();">Google</a>',
'<a>Google</a>'
);
}
function testImg() {
function testImgAddDefaults() {
$this->config->set('Core', 'RemoveInvalidImg', false);
$this->assertResult(
'<img />',
'<img src="" alt="Invalid image" />',
array('Core.RemoveInvalidImg' => false)
'<img src="" alt="Invalid image" />'
);
}
function testImgGenerateAlt() {
$this->assertResult(
'<img src="foobar.jpg" />',
'<img src="foobar.jpg" alt="foobar.jpg" />'
);
}
function testImgAddDefaultSrc() {
$this->config->set('Core', 'RemoveInvalidImg', false);
$this->assertResult(
'<img alt="pretty picture" />',
'<img alt="pretty picture" src="" />',
array('Core.RemoveInvalidImg' => false)
'<img alt="pretty picture" src="" />'
);
// mailto in image is not allowed
}
function testImgRemoveNonRetrievableProtocol() {
$this->config->set('Core', 'RemoveInvalidImg', false);
$this->assertResult(
'<img src="mailto:foo@example.com" />',
'<img alt="mailto:foo@example.com" src="" />',
array('Core.RemoveInvalidImg' => false)
);
// align transformation
$this->assertResult(
'<img src="foobar.jpg" alt="foobar" align="left" />',
'<img src="foobar.jpg" alt="foobar" style="float:left;" />'
);
$this->assertResult(
'<img src="foobar.jpg" alt="foobar" align="right" />',
'<img src="foobar.jpg" alt="foobar" style="float:right;" />'
);
$this->assertResult(
'<img src="foobar.jpg" alt="foobar" align="bottom" />',
'<img src="foobar.jpg" alt="foobar" style="vertical-align:baseline;" />'
);
$this->assertResult(
'<img src="foobar.jpg" alt="foobar" align="middle" />',
'<img src="foobar.jpg" alt="foobar" style="vertical-align:middle;" />'
);
$this->assertResult(
'<img src="foobar.jpg" alt="foobar" align="top" />',
'<img src="foobar.jpg" alt="foobar" style="vertical-align:top;" />'
);
$this->assertResult(
'<img src="foobar.jpg" alt="foobar" align="outerspace" />',
'<img src="foobar.jpg" alt="foobar" />'
);
}
function testBdo() {
// test required attributes for bdo
$this->assertResult(
'<bdo>Go left.</bdo>',
'<bdo dir="ltr">Go left.</bdo>'
);
$this->assertResult(
'<bdo dir="blahblah">Invalid value!</bdo>',
'<bdo dir="ltr">Invalid value!</bdo>'
'<img alt="mailto:foo@example.com" src="" />'
);
}
function testDir() {
// see testBdo, behavior is subtly different
$this->assertResult(
'<span dir="blahblah">Invalid value!</span>',
'<span>Invalid value!</span>'
);
function testPreserveRel() {
$this->config->set('Attr', 'AllowedRel', 'nofollow');
$this->assertResult('<a href="foo" rel="nofollow" />');
}
function testLinks() {
// link types
$this->assertResult(
'<a href="foo" rel="nofollow" />',
true,
array('Attr.AllowedRel' => 'nofollow')
);
// link targets
$this->assertResult(
'<a href="foo" target="_top" />',
true,
array('Attr.AllowedFrameTargets' => '_top',
'HTML.Doctype' => 'XHTML 1.0 Transitional')
);
function testPreserveTarget() {
$this->config->set('Attr', 'AllowedFrameTargets', '_top');
$this->config->set('HTML', 'Doctype', 'XHTML 1.0 Transitional');
$this->assertResult('<a href="foo" target="_top" />');
}
function testRemoveTargetWhenNotSupported() {
$this->config->set('HTML', 'Doctype', 'XHTML 1.0 Strict');
$this->config->set('Attr', 'AllowedFrameTargets', '_top');
$this->assertResult(
'<a href="foo" target="_top" />',
'<a href="foo" />'
);
$this->assertResult(
'<a href="foo" target="_top" />',
'<a href="foo" />',
array('Attr.AllowedFrameTargets' => '_top', 'HTML.Strict' => true)
);
}
function testBorder() {
// border
$this->assertResult(
'<img src="foo" alt="foo" hspace="1" vspace="3" />',
'<img src="foo" alt="foo" style="margin-top:3px;margin-bottom:3px;margin-left:1px;margin-right:1px;" />',
array('Attr.AllowedRel' => 'nofollow')
);
}
function testHr() {
$this->assertResult(
'<hr size="3" />',
'<hr style="height:3px;" />'
);
$this->assertResult(
'<hr noshade />',
'<hr style="color:#808080;background-color:#808080;border:0;" />'
);
// align transformation
$this->assertResult(
'<hr align="left" />',
'<hr style="margin-left:0;margin-right:auto;text-align:left;" />'
);
$this->assertResult(
'<hr align="center" />',
'<hr style="margin-left:auto;margin-right:auto;text-align:center;" />'
);
$this->assertResult(
'<hr align="right" />',
'<hr style="margin-left:auto;margin-right:0;text-align:right;" />'
);
$this->assertResult(
'<hr align="bottom" />',
'<hr />'
);
}
function testBr() {
// br clear transformation
$this->assertResult(
'<br clear="left" />',
'<br style="clear:left;" />'
);
$this->assertResult(
'<br clear="right" />',
'<br style="clear:right;" />'
);
$this->assertResult( // test both?
'<br clear="all" />',
'<br style="clear:both;" />'
);
$this->assertResult(
'<br clear="none" />',
'<br style="clear:none;" />'
);
$this->assertResult(
'<br clear="foo" />',
'<br />'
);
}
function testListTypeTransform() {
// ul
$this->assertResult(
'<ul type="disc" />',
'<ul style="list-style-type:disc;" />'
);
$this->assertResult(
'<ul type="square" />',
'<ul style="list-style-type:square;" />'
);
$this->assertResult(
'<ul type="circle" />',
'<ul style="list-style-type:circle;" />'
);
$this->assertResult( // case insensitive
'<ul type="CIRCLE" />',
'<ul style="list-style-type:circle;" />'
);
$this->assertResult(
'<ul type="a" />',
'<ul />'
);
// ol
$this->assertResult(
'<ol type="1" />',
'<ol style="list-style-type:decimal;" />'
);
$this->assertResult(
'<ol type="i" />',
'<ol style="list-style-type:lower-roman;" />'
);
$this->assertResult(
'<ol type="I" />',
'<ol style="list-style-type:upper-roman;" />'
);
$this->assertResult(
'<ol type="a" />',
'<ol style="list-style-type:lower-alpha;" />'
);
$this->assertResult(
'<ol type="A" />',
'<ol style="list-style-type:upper-alpha;" />'
);
$this->assertResult(
'<ol type="disc" />',
'<ol />'
);
// li
$this->assertResult(
'<li type="circle" />',
'<li style="list-style-type:circle;" />'
);
$this->assertResult(
'<li type="A" />',
'<li style="list-style-type:upper-alpha;" />'
);
$this->assertResult( // case sensitive
'<li type="CIRCLE" />',
'<li />'
);
}
}

View File

@ -98,9 +98,13 @@ $test_files[] = 'HTMLPurifier/Strategy/FixNestingTest.php';
$test_files[] = 'HTMLPurifier/Strategy/FixNesting_ErrorsTest.php';
$test_files[] = 'HTMLPurifier/Strategy/MakeWellFormedTest.php';
$test_files[] = 'HTMLPurifier/Strategy/MakeWellFormed_ErrorsTest.php';
$test_files[] = 'HTMLPurifier/Strategy/MakeWellFormed_InjectorTest.php';
$test_files[] = 'HTMLPurifier/Strategy/RemoveForeignElementsTest.php';
$test_files[] = 'HTMLPurifier/Strategy/RemoveForeignElements_ErrorsTest.php';
$test_files[] = 'HTMLPurifier/Strategy/RemoveForeignElements_TidyTest.php';
$test_files[] = 'HTMLPurifier/Strategy/ValidateAttributesTest.php';
$test_files[] = 'HTMLPurifier/Strategy/ValidateAttributes_IDTest.php';
$test_files[] = 'HTMLPurifier/Strategy/ValidateAttributes_TidyTest.php';
$test_files[] = 'HTMLPurifier/TagTransformTest.php';
$test_files[] = 'HTMLPurifier/TokenTest.php';
$test_files[] = 'HTMLPurifier/URIDefinitionTest.php';