From 436370e59daf31aaa7b5047a4b411b0d2686453a Mon Sep 17 00:00:00 2001 From: Coren Date: Sat, 16 Apr 2016 16:15:15 +0000 Subject: [PATCH] Add unit tests for CSSParse and CSSRender Test the roundtrip on a collection of correct and pathological stylesheets to ascertain whether the parse is behaving as expected. Bug: T483 Change-Id: I484cc856b5696c1fa6265769320f79853365e1d6 --- TemplateStyles.hooks.php | 5 + extension.json | 3 + tests/CSSParseRenderTest.php | 237 +++++++++++++++++++++++++++++++++++ 3 files changed, 245 insertions(+) create mode 100644 tests/CSSParseRenderTest.php diff --git a/TemplateStyles.hooks.php b/TemplateStyles.hooks.php index 9a0c0c7..b75e356 100644 --- a/TemplateStyles.hooks.php +++ b/TemplateStyles.hooks.php @@ -15,6 +15,11 @@ class TemplateStylesHooks { return true; } + public static function onUnitTestsList( &$paths ) { + $paths[] = __DIR__ . '/tests/phpunit/'; + return true; + } + private static function decodeFromBlob( $blob ) { $tree = gzdecode( $blob ); if ( $tree ) { diff --git a/extension.json b/extension.json index 3e0f3e0..13f787a 100644 --- a/extension.json +++ b/extension.json @@ -36,6 +36,9 @@ ], "OutputPageParserOutput": [ "TemplateStylesHooks::onOutputPageParserOutput" + ], + "UnitTestList": [ + "TemplateStyleHooks::onUnitTestList" ] } } diff --git a/tests/CSSParseRenderTest.php b/tests/CSSParseRenderTest.php new file mode 100644 index 0000000..3ebff59 --- /dev/null +++ b/tests/CSSParseRenderTest.php @@ -0,0 +1,237 @@ + 'Bare declaration', + 'expect' => '', + 'css' => << 'Blacklisted property', + 'expect' => '.X .sel {good:123;} ', + 'css' => << 'Case insensivity', + 'expect' => '@media screen { .X .sel1 {prop:WhiteListed(foo);} } ', + 'css' => << 'Comment trickery', + 'expect' => '.X .sel1 {} .X .sel2 .sel3 {prop3:val3;} ', + 'css' => << 'Complex selectors', + 'expect' => '.X .sel1[foo=\'ba{r\'] #id a.foo::hover {prop1:val1;} ', + 'css' => << 'Edge cases', + 'expect' => '.X :sel {} ', + 'css' => << 'Function in function', + 'expect' => '.X .sel1 {} ', + 'css' => << 'Incomplete rule', + 'expect' => '.X .sel {prop:val;} ', + 'css' => << 'Media block', + 'expect' => '.X .sel2 {prop2:val2;} @media print { .X .sel1 {prop1:val1;} } ', + 'css' => << 'Multiple rules', + 'expect' => '.X .sel1 A {prop1:val1;} .X T.sel2 {prop2:val2;} ', + 'css' => << 'Multiple selectors', + 'expect' => '.X .sel1,.X TD .sel2["a,comma"],.X #id {prop:val;} ', + 'css' => << 'No selector', + 'expect' => '{prop1:val1;} ', + 'css' => << 'Not a declaration', + 'expect' => '.X .sel {prop:val;} ', + 'css' => << 'Obfuscated properties', + 'expect' => '.X .sel {good:val2;} ', + 'css' => << 'Rule within rule', + 'expect' => '.X .sel1 {prop1:val1;} .X .sel3 {prop4:val4;} ', + 'css' => << 'String literals', + 'expect' => '.X .sel {prop1:\'val1\';prop3:"v/**/al\"3";bad:"broken" ;} ', + 'css' => << 'Unsupported block', + 'expect' => '.X .sel {prop2:val2;} ', + 'css' => << 'Unwhitelisted function', + 'expect' => '.X .sel {prop1:whitelisted(val1);} ', + 'css' => << 'Values', + 'expect' => '.X .sel {prop:1em .5px 12% #FFF;} ', + 'css' => << 'Whitespace', + 'expect' => '.X .sel1 #id{prop2:whitelisted ( val2 ) ;prop3:not whitelisted( val3 );} ', + 'css' => <<rules( '.X ' ); + if ( !$rules ) { + $this->fail( "$test: Stylesheet did not parse." ); + return; + } + + $r = new CSSRenderer(); + $r->add( $rules ); + $css = $r->render( [ "whitelisted" ], [ "-evil" ] ); + + $this->assertEquals( + $expect, + preg_replace( '/[ \t\n]+/', ' ', $css ), + "$test: parse did not return expected output." + ); + + } + +} +