SECURITY: blacklist CSS var()
[lhc/web/wiklou.git] / tests / phpunit / includes / HtmlTest.php
index 3c8fa25..999e0bb 100644 (file)
@@ -1,6 +1,7 @@
 <?php
 
 class HtmlTest extends MediaWikiTestCase {
+       private $restoreWarnings;
 
        protected function setUp() {
                parent::setUp();
@@ -9,12 +10,12 @@ class HtmlTest extends MediaWikiTestCase {
                        'wgUseMediaWikiUIEverywhere' => false,
                ] );
 
-               $langObj = Language::factory( 'en' );
+               $contLangObj = Language::factory( 'en' );
 
                // Hardcode namespaces during test runs,
                // so that html output based on existing namespaces
                // can be properly evaluated.
-               $langObj->setNamespaces( [
+               $contLangObj->setNamespaces( [
                        -2 => 'Media',
                        -1 => 'Special',
                        0 => '',
@@ -34,8 +35,54 @@ class HtmlTest extends MediaWikiTestCase {
                        100 => 'Custom',
                        101 => 'Custom_talk',
                ] );
-               $this->setUserLang( $langObj );
-               $this->setContentLang( $langObj );
+               $this->setContentLang( $contLangObj );
+
+               $userLangObj = Language::factory( 'es' );
+               $userLangObj->setNamespaces( [
+                       -2 => "Medio",
+                       -1 => "Especial",
+                       0 => "",
+                       1 => "Discusión",
+                       2 => "Usuario",
+                       3 => "Usuario discusión",
+                       4 => "Wiki",
+                       5 => "Wiki discusión",
+                       6 => "Archivo",
+                       7 => "Archivo discusión",
+                       8 => "MediaWiki",
+                       9 => "MediaWiki discusión",
+                       10 => "Plantilla",
+                       11 => "Plantilla discusión",
+                       12 => "Ayuda",
+                       13 => "Ayuda discusión",
+                       14 => "Categoría",
+                       15 => "Categoría discusión",
+                       100 => "Personalizado",
+                       101 => "Personalizado discusión",
+               ] );
+               $this->setUserLang( $userLangObj );
+
+               $this->restoreWarnings = false;
+       }
+
+       protected function tearDown() {
+               Language::factory( 'en' )->resetNamespaces();
+
+               if ( $this->restoreWarnings ) {
+                       $this->restoreWarnings = false;
+                       Wikimedia\restoreWarnings();
+               }
+
+               parent::tearDown();
+       }
+
+       /**
+        * @expectedException PHPUnit_Framework_Error_Notice
+        * @expectedExceptionMessage given element name with space
+        * @covers Html::openElement
+        */
+       public function testOpenElement() {
+               Html::openElement( 'span id="x"' );
        }
 
        /**
@@ -165,7 +212,6 @@ class HtmlTest extends MediaWikiTestCase {
        }
 
        /**
-        * Test for Html::expandAttributes()
         * Please note it output a string prefixed with a space!
         * @covers Html::expandAttributes
         */
@@ -309,7 +355,7 @@ class HtmlTest extends MediaWikiTestCase {
        public function testNamespaceSelector() {
                $this->assertEquals(
                        '<select id="namespace" name="namespace">' . "\n" .
-                               '<option value="0">(Main)</option>' . "\n" .
+                               '<option value="0">(Principal)</option>' . "\n" .
                                '<option value="1">Talk</option>' . "\n" .
                                '<option value="2">User</option>' . "\n" .
                                '<option value="3">User talk</option>' . "\n" .
@@ -333,8 +379,8 @@ class HtmlTest extends MediaWikiTestCase {
                $this->assertEquals(
                        '<label for="mw-test-namespace">Select a namespace:</label>' . "\u{00A0}" .
                                '<select id="mw-test-namespace" name="wpNamespace">' . "\n" .
-                               '<option value="all">all</option>' . "\n" .
-                               '<option value="0">(Main)</option>' . "\n" .
+                               '<option value="all">todos</option>' . "\n" .
+                               '<option value="0">(Principal)</option>' . "\n" .
                                '<option value="1">Talk</option>' . "\n" .
                                '<option value="2" selected="">User</option>' . "\n" .
                                '<option value="3">User talk</option>' . "\n" .
@@ -361,7 +407,7 @@ class HtmlTest extends MediaWikiTestCase {
                $this->assertEquals(
                        '<label for="namespace">Select a namespace:</label>' . "\u{00A0}" .
                                '<select id="namespace" name="namespace">' . "\n" .
-                               '<option value="0">(Main)</option>' . "\n" .
+                               '<option value="0">(Principal)</option>' . "\n" .
                                '<option value="1">Talk</option>' . "\n" .
                                '<option value="2">User</option>' . "\n" .
                                '<option value="3">User talk</option>' . "\n" .
@@ -383,6 +429,33 @@ class HtmlTest extends MediaWikiTestCase {
                        ),
                        'Basic namespace selector with a custom label but no id attribtue for the <select>'
                );
+
+               $this->assertEquals(
+                       '<select id="namespace" name="namespace">' . "\n" .
+                               '<option value="0">(Principal)</option>' . "\n" .
+                               '<option value="1">Discusión</option>' . "\n" .
+                               '<option value="2">Usuario</option>' . "\n" .
+                               '<option value="3">Usuario discusión</option>' . "\n" .
+                               '<option value="4">Wiki</option>' . "\n" .
+                               '<option value="5">Wiki discusión</option>' . "\n" .
+                               '<option value="6">Archivo</option>' . "\n" .
+                               '<option value="7">Archivo discusión</option>' . "\n" .
+                               '<option value="8">MediaWiki</option>' . "\n" .
+                               '<option value="9">MediaWiki discusión</option>' . "\n" .
+                               '<option value="10">Plantilla</option>' . "\n" .
+                               '<option value="11">Plantilla discusión</option>' . "\n" .
+                               '<option value="12">Ayuda</option>' . "\n" .
+                               '<option value="13">Ayuda discusión</option>' . "\n" .
+                               '<option value="14">Categoría</option>' . "\n" .
+                               '<option value="15">Categoría discusión</option>' . "\n" .
+                               '<option value="100">Personalizado</option>' . "\n" .
+                               '<option value="101">Personalizado discusión</option>' . "\n" .
+                               '</select>',
+                       Html::namespaceSelector(
+                               [ 'in-user-lang' => true ]
+                       ),
+                       'Basic namespace selector in user language'
+               );
        }
 
        /**
@@ -416,7 +489,7 @@ class HtmlTest extends MediaWikiTestCase {
        public function testCanDisableANamespaces() {
                $this->assertEquals(
                        '<select id="namespace" name="namespace">' . "\n" .
-                               '<option disabled="" value="0">(Main)</option>' . "\n" .
+                               '<option disabled="" value="0">(Principal)</option>' . "\n" .
                                '<option disabled="" value="1">Talk</option>' . "\n" .
                                '<option disabled="" value="2">User</option>' . "\n" .
                                '<option disabled="" value="3">User talk</option>' . "\n" .
@@ -476,6 +549,10 @@ class HtmlTest extends MediaWikiTestCase {
                        Html::errorBox( 'err', 'heading' ),
                        '<div class="errorbox"><h2>heading</h2>err</div>'
                );
+               $this->assertEquals(
+                       Html::errorBox( 'err', '0' ),
+                       '<div class="errorbox"><h2>0</h2>err</div>'
+               );
        }
 
        /**
@@ -785,6 +862,58 @@ class HtmlTest extends MediaWikiTestCase {
        public function testSrcSet( $images, $expected, $message ) {
                $this->assertEquals( Html::srcSet( $images ), $expected, $message );
        }
+
+       public static function provideInlineScript() {
+               return [
+                       'Empty' => [
+                               '',
+                               '<script></script>'
+                       ],
+                       'Simple' => [
+                               'EXAMPLE.label("foo");',
+                               '<script>EXAMPLE.label("foo");</script>'
+                       ],
+                       'Ampersand' => [
+                               'EXAMPLE.is(a && b);',
+                               '<script>EXAMPLE.is(a && b);</script>'
+                       ],
+                       'HTML' => [
+                               'EXAMPLE.label("<a>");',
+                               '<script>EXAMPLE.label("<a>");</script>'
+                       ],
+                       'Script closing string (lower)' => [
+                               'EXAMPLE.label("</script>");',
+                               '<script>/* ERROR: Invalid script */</script>',
+                               true,
+                       ],
+                       'Script closing with non-standard attributes (mixed)' => [
+                               'EXAMPLE.label("</SCriPT and STyLE>");',
+                               '<script>/* ERROR: Invalid script */</script>',
+                               true,
+                       ],
+                       'HTML-comment-open and script-open' => [
+                               // In HTML, <script> contents aren't just plain CDATA until </script>,
+                               // there are levels of escaping modes, and the below sequence puts an
+                               // HTML parser in a state where </script> would *not* close the script.
+                               // https://html.spec.whatwg.org/multipage/parsing.html#script-data-double-escape-end-state
+                               'var a = "<!--<script>";',
+                               '<script>/* ERROR: Invalid script */</script>',
+                               true,
+                       ],
+               ];
+       }
+
+       /**
+        * @dataProvider provideInlineScript
+        * @covers Html::inlineScript
+        */
+       public function testInlineScript( $code, $expected, $error = false ) {
+               if ( $error ) {
+                       Wikimedia\suppressWarnings();
+                       $this->restoreWarnings = true;
+               }
+               $this->assertSame( Html::inlineScript( $code ), $expected );
+       }
 }
 
 class HtmlTestValue {