summaryrefslogtreecommitdiff
path: root/www/wiki/skins/chameleon/tests
diff options
context:
space:
mode:
authorYaco <franco@reevo.org>2020-06-04 11:01:00 -0300
committerYaco <franco@reevo.org>2020-06-04 11:01:00 -0300
commitfc7369835258467bf97eb64f184b93691f9a9fd5 (patch)
treedaabd60089d2dd76d9f5fb416b005fbe159c799d /www/wiki/skins/chameleon/tests
first commit
Diffstat (limited to 'www/wiki/skins/chameleon/tests')
-rw-r--r--www/wiki/skins/chameleon/tests/bootstrap.php77
-rw-r--r--www/wiki/skins/chameleon/tests/mw-phpunit-runner.php91
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/Cell.xml5
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/Container.xml5
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/FooterIcons.xml5
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/FooterInfo.xml5
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/FooterPlaces.xml4
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/Grid.xml5
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/Html.xml9
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/Logo.xml5
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/MainContent.xml5
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/Menu.xml5
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/Modifications/HideFor.xml5
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/Modifications/ShowOnlyFor.xml5
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/NavMenu.xml5
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/NavbarHorizontal.xml11
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/NavbarHorizontal/PageToolsAdaptable.xml5
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/NavbarHorizontal/PersonalTools.xml5
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/NewtalkNotifier.xml5
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/PageTools.xml5
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/PersonalTools.xml5
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/Row.xml5
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/SearchBar.xml4
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/Silent.xml5
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/SiteNotice.xml4
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/Structure.xml2
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/ToolbarHorizontal.xml4
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Fixture/externalmodule.less0
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Integration/StylesCompileTest.php75
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Integration/XmlLayoutFileValidityTest.php68
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/ChameleonTemplateTest.php83
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/CellTest.php98
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/ComponentTest.php340
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/ContainerTest.php44
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/FooterIconsTest.php85
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/FooterInfoTest.php78
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/FooterPlacesTest.php71
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/GenericComponentTestCase.php345
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/GridTest.php44
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/HtmlTest.php67
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/LogoTest.php44
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/MainContentTest.php63
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/MenuTest.php44
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/Modifications/GenericModificationTestCase.php57
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/Modifications/HideForTest.php44
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/Modifications/ShowOnlyForTest.php44
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/NavMenuTest.php44
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/NavbarHorizontalTest.php78
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/NavbarHorizontral/PageToolsAdaptableTest.php326
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/NavbarHorizontral/PersonalToolsTest.php84
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/NewtalkNotifierTest.php44
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/PageToolsTest.php44
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/PersonalToolsTest.php44
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/RowTest.php44
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/SearchBarTest.php44
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/SilentTest.php44
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/SiteNoticeTest.php44
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/StructureTest.php57
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Components/ToolbarHorizontalTest.php44
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Hooks/SetupAfterCacheTest.php498
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Unit/Menu/MenuFromLinesTest.php127
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Util/ColoringTextUIResultPrinter.php105
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Util/DocumentElementFinder.php124
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Util/MockupFactory.php335
-rw-r--r--www/wiki/skins/chameleon/tests/phpunit/Util/XmlFileProvider.php85
65 files changed, 4205 insertions, 0 deletions
diff --git a/www/wiki/skins/chameleon/tests/bootstrap.php b/www/wiki/skins/chameleon/tests/bootstrap.php
new file mode 100644
index 00000000..4b235aee
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/bootstrap.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2016, Stephan Gambke, mwjames
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author mwjames
+ * @since 1.0
+ * @ingroup Skins
+ */
+
+if ( php_sapi_name() !== 'cli' ) {
+ die( 'Not an entry point' );
+}
+
+if ( !defined( 'MEDIAWIKI' ) ) {
+ die( 'MediaWiki is not available for the test environment' );
+}
+
+function registerAutoloaderPath( $identifier, $path ) {
+ print( "\nUsing the {$identifier} vendor autoloader ...\n\n" );
+ return require $path;
+}
+
+/**
+ * @return string
+ */
+function getDirectory() {
+
+ $directory = $GLOBALS[ 'argv' ][ 0 ];
+
+ if ( $directory[ 0 ] !== DIRECTORY_SEPARATOR ) {
+ $directory = $_SERVER[ 'PWD' ] . DIRECTORY_SEPARATOR . $directory;
+ }
+
+ $directory = dirname( $directory );
+
+ return $directory;
+}
+
+function runTestAutoLoader( $autoLoader = null ) {
+
+ $directory = getDirectory();
+
+ $mwVendorPath = $directory . '/../../vendor/autoload.php';
+ $localVendorPath = $directory . '/../vendor/autoload.php';
+
+ if ( is_readable( $localVendorPath ) ) {
+ $autoLoader = registerAutoloaderPath( 'local', $localVendorPath );
+ } elseif ( is_readable( $mwVendorPath ) ) {
+ $autoLoader = registerAutoloaderPath( 'MediaWiki', $mwVendorPath );
+ }
+
+ if ( !$autoLoader instanceof \Composer\Autoload\ClassLoader ) {
+ return false;
+ }
+
+ return true;
+}
+
+if ( !runTestAutoLoader() ) {
+ die( 'Required test class loader was not accessible' );
+}
diff --git a/www/wiki/skins/chameleon/tests/mw-phpunit-runner.php b/www/wiki/skins/chameleon/tests/mw-phpunit-runner.php
new file mode 100644
index 00000000..11de0750
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/mw-phpunit-runner.php
@@ -0,0 +1,91 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2016, Stephan Gambke, mwjames
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author mwjames
+ * @since 1.0
+ * @ingroup Skins
+ */
+
+
+/**
+ * Lazy script to invoke the MediaWiki phpunit runner
+ *
+ * php mw-phpunit-runner.php [options]
+ */
+
+if ( php_sapi_name() !== 'cli' ) {
+ die( 'Not an entry point' );
+}
+
+print( "\nMediaWiki phpunit runnner ... \n" );
+
+function isReadablePath( $path ) {
+
+ if ( is_readable( $path ) ) {
+ return $path;
+ }
+
+ throw new RuntimeException( "Expected an accessible {$path} path" );
+}
+
+function addArguments( $args ) {
+
+ array_shift( $args );
+ return $args;
+
+// $arguments = array();
+//
+// for ( $arg = reset( $args ); $arg !== false; $arg = next( $args ) ) {
+//
+// //// FIXME: This check will fail if started from a different directory
+// if ( $arg === basename( __FILE__ ) ) {
+// continue;
+// }
+//
+// $arguments[] = $arg;
+// }
+//
+// return $arguments;
+}
+
+/**
+ * @return string
+ */
+function getDirectory() {
+
+ $directory = $GLOBALS[ 'argv' ][ 0 ];
+
+ if ( $directory[ 0 ] !== DIRECTORY_SEPARATOR ) {
+ $directory = $_SERVER[ 'PWD' ] . DIRECTORY_SEPARATOR . $directory;
+ }
+
+ $directory = dirname( $directory );
+
+ return $directory;
+}
+
+$skinDirectory = dirname ( getDirectory() );
+
+$config = isReadablePath( "$skinDirectory/phpunit.xml.dist" );
+$mw = isReadablePath( dirname( dirname( $skinDirectory ) ) . "/tests/phpunit/phpunit.php" );
+
+echo "php {$mw} -c {$config} " . implode( ' ', addArguments( $GLOBALS['argv'] ) );
+
+passthru( "php {$mw} -c {$config} " . implode( ' ', addArguments( $GLOBALS['argv'] ) ) );
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/Cell.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/Cell.xml
new file mode 100644
index 00000000..647c2966
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/Cell.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure>
+ <cell span="12"></cell>
+</structure>
+
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/Container.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/Container.xml
new file mode 100644
index 00000000..ff6a5602
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/Container.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure>
+ <component type="Container"></component>
+</structure>
+
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/FooterIcons.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/FooterIcons.xml
new file mode 100644
index 00000000..a74cec75
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/FooterIcons.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure>
+ <component type="FooterIcons"></component>
+</structure>
+
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/FooterInfo.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/FooterInfo.xml
new file mode 100644
index 00000000..abd09508
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/FooterInfo.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure>
+ <component type="FooterInfo"></component>
+</structure>
+
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/FooterPlaces.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/FooterPlaces.xml
new file mode 100644
index 00000000..8965790c
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/FooterPlaces.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure>
+<component type="FooterPlaces"></component>
+</structure>
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/Grid.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/Grid.xml
new file mode 100644
index 00000000..1bf36c6c
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/Grid.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure>
+ <grid></grid>
+</structure>
+
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/Html.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/Html.xml
new file mode 100644
index 00000000..805d73bf
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/Html.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure>
+ <component type="Html">
+ <div>foo</div>
+ bar
+ <span>baz</span>
+ </component>
+</structure>
+
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/Logo.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/Logo.xml
new file mode 100644
index 00000000..9a59bb05
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/Logo.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure>
+ <component type="Logo"></component>
+</structure>
+
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/MainContent.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/MainContent.xml
new file mode 100644
index 00000000..8f25f80e
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/MainContent.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure>
+ <component type="MainContent"></component>
+</structure>
+
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/Menu.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/Menu.xml
new file mode 100644
index 00000000..24b941b9
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/Menu.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure>
+ <component type="Menu"></component>
+</structure>
+
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/Modifications/HideFor.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/Modifications/HideFor.xml
new file mode 100644
index 00000000..ce9d395a
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/Modifications/HideFor.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure>
+ <modification type="HideFor"></modification>
+</structure>
+
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/Modifications/ShowOnlyFor.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/Modifications/ShowOnlyFor.xml
new file mode 100644
index 00000000..48f1637c
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/Modifications/ShowOnlyFor.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure>
+ <modification type="ShowOnlyFor"></modification>
+</structure>
+
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/NavMenu.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/NavMenu.xml
new file mode 100644
index 00000000..3a56279f
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/NavMenu.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure>
+ <component type="NavMenu"></component>
+</structure>
+
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/NavbarHorizontal.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/NavbarHorizontal.xml
new file mode 100644
index 00000000..d7505684
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/NavbarHorizontal.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure>
+ <component type="NavbarHorizontal">
+ <component type="Logo"></component>
+ <component type="NavMenu" flatten="navigation"></component>
+ <component type="PageTools" hideSelectedNameSpace="1"></component>
+ <component type="PersonalTools"></component>
+ <component type="SearchBar"></component>
+ </component>
+</structure>
+
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/NavbarHorizontal/PageToolsAdaptable.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/NavbarHorizontal/PageToolsAdaptable.xml
new file mode 100644
index 00000000..0af37bdc
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/NavbarHorizontal/PageToolsAdaptable.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure>
+ <component type="PageToolsAdaptable" show="view,edit,history"></component>
+</structure>
+
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/NavbarHorizontal/PersonalTools.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/NavbarHorizontal/PersonalTools.xml
new file mode 100644
index 00000000..32bab95b
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/NavbarHorizontal/PersonalTools.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure>
+ <component type="PersonalTools"></component>
+</structure>
+
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/NewtalkNotifier.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/NewtalkNotifier.xml
new file mode 100644
index 00000000..2cc62075
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/NewtalkNotifier.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure>
+ <component type="NewtalkNotifier"></component>
+</structure>
+
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/PageTools.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/PageTools.xml
new file mode 100644
index 00000000..6eadb071
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/PageTools.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure>
+ <component type="PageTools"></component>
+</structure>
+
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/PersonalTools.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/PersonalTools.xml
new file mode 100644
index 00000000..32bab95b
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/PersonalTools.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure>
+ <component type="PersonalTools"></component>
+</structure>
+
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/Row.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/Row.xml
new file mode 100644
index 00000000..c6cd0c72
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/Row.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure>
+ <row></row>
+</structure>
+
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/SearchBar.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/SearchBar.xml
new file mode 100644
index 00000000..d5a01501
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/SearchBar.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure>
+ <component type="SearchBar"></component>
+</structure>
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/Silent.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/Silent.xml
new file mode 100644
index 00000000..7837e5c7
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/Silent.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure>
+ <component type="Silent"></component>
+</structure>
+
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/SiteNotice.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/SiteNotice.xml
new file mode 100644
index 00000000..c48b5227
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/SiteNotice.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure>
+ <component type="SiteNotice"></component>
+</structure>
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/Structure.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/Structure.xml
new file mode 100644
index 00000000..48e0e075
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/Structure.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure></structure>
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/ToolbarHorizontal.xml b/www/wiki/skins/chameleon/tests/phpunit/Fixture/ToolbarHorizontal.xml
new file mode 100644
index 00000000..bcf07956
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/ToolbarHorizontal.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<structure>
+ <component type="ToolbarHorizontal"></component>
+</structure>
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Fixture/externalmodule.less b/www/wiki/skins/chameleon/tests/phpunit/Fixture/externalmodule.less
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Fixture/externalmodule.less
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Integration/StylesCompileTest.php b/www/wiki/skins/chameleon/tests/phpunit/Integration/StylesCompileTest.php
new file mode 100644
index 00000000..0b328dfd
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Integration/StylesCompileTest.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Integration;
+
+use Bootstrap\BootstrapManager;
+use Bootstrap\ResourceLoaderBootstrapModule;
+use CSSMin;
+use HashBagOStuff;
+use Skins\Chameleon\Hooks\SetupAfterCache;
+
+/**
+ * @coversNothing
+ *
+ * @group skins-chameleon
+ * @group skins-chameleon-integration
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.1
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class StylesCompileTest extends \PHPUnit_Framework_TestCase {
+
+ public function testStylesCompile() {
+
+ $request = $this->getMockBuilder('\WebRequest')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $setupAfterCache = new SetupAfterCache(
+ BootstrapManager::getInstance(),
+ $GLOBALS,
+ $request
+ );
+
+ $setupAfterCache->process();
+
+ $resourceLoaderContext = $this->getMockBuilder( '\ResourceLoaderContext' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $module = new ResourceLoaderBootstrapModule( $GLOBALS[ 'wgResourceModules' ][ 'ext.bootstrap.styles' ] );
+ $module->setCache( new HashBagOStuff() );
+
+ $styles = $module->getStyles( $resourceLoaderContext );
+ $css = CSSMin::minify( $styles[ 'all' ] );
+
+ $this->assertNotEquals( '', $css );
+
+ }
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Integration/XmlLayoutFileValidityTest.php b/www/wiki/skins/chameleon/tests/phpunit/Integration/XmlLayoutFileValidityTest.php
new file mode 100644
index 00000000..caea8287
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Integration/XmlLayoutFileValidityTest.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke, mwjames
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Integration;
+
+use Skins\Chameleon\Tests\Util\XmlFileProvider;
+
+use DOMDocument;
+use RuntimeException;
+
+/**
+ * @coversNothing
+ *
+ * @group skins-chameleon
+ * @group skins-chameleon-integration
+ * @group mediawiki-databaseless
+ *
+ * @author mwjames
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class XmlLayoutFileValidityTest extends \PHPUnit_Framework_TestCase {
+
+ public function testXmlValidityOfLayoutFiles() {
+
+ $xmlFileProvider = new XmlFileProvider( __DIR__ . '/../../../layouts' );
+
+ $listOfLayoutXmlFiles = $xmlFileProvider->getFiles();
+
+ $this->assertNotEmpty( $listOfLayoutXmlFiles );
+ $this->assertXmlFiles( $listOfLayoutXmlFiles );
+ }
+
+ protected function assertXmlFiles( $files ) {
+ foreach ( $files as $file ) {
+ $this->assertXmlDocumentLoad( $file );
+ }
+ }
+
+ protected function assertXmlDocumentLoad( $file ) {
+ $document = new DOMDocument();
+ $document->validateOnParse = false;
+ $this->assertTrue( $document->load( $file ) );
+ }
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/ChameleonTemplateTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/ChameleonTemplateTest.php
new file mode 100644
index 00000000..ea0e89ef
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/ChameleonTemplateTest.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke, mwjames
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit;
+
+use Skins\Chameleon\ChameleonTemplate;
+
+/**
+ * @uses \Skins\Chameleon\ChameleonTemplate
+ *
+ * @group skins-chameleon
+ * @group skins-chameleon-unit
+ * @group mediawiki-databaseless
+ *
+ * @license GNU GPL v3+
+ * @since 1.0
+ *
+ * @author mwjames
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class ChameleonTemplateTest extends \PHPUnit_Framework_TestCase {
+
+ // This is to ensure that the original value is cached since we are unable
+ // to inject the setting during testing
+ protected $egChameleonLayoutFile = null;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->egChameleonLayoutFile = $GLOBALS['egChameleonLayoutFile'];
+ }
+
+ protected function tearDown() {
+ $GLOBALS['egChameleonLayoutFile'] = $this->egChameleonLayoutFile;
+
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\Skins\Chameleon\ChameleonTemplate',
+ new ChameleonTemplate()
+ );
+ }
+
+ public function testInaccessibleLayoutFileThrowsExeception() {
+
+ $this->setExpectedException( 'RuntimeException' );
+
+ $GLOBALS['egChameleonLayoutFile'] = 'setInaccessibleLayoutFile';
+
+ $skin = new \SkinChameleon();
+
+ $instance = new ChameleonTemplate;
+ $instance->set( 'skin', $skin );
+ $instance->execute();
+ }
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/CellTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/CellTest.php
new file mode 100644
index 00000000..ddd9df82
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/CellTest.php
@@ -0,0 +1,98 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\Cell
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class CellTest extends GenericComponentTestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\Cell';
+
+ /**
+ * @covers ::__construct
+ * @dataProvider provideSpanAttributeValues
+ * @param string $in
+ * @param string $expected
+ */
+ public function testSpanAttribute( $in, $expected ) {
+
+ $chameleonTemplate = $this->getMockBuilder( '\Skins\Chameleon\ChameleonTemplate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $domElement = $this->getMockBuilder( '\DOMElement' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $domElement->expects( $this->any() )
+ ->method( 'getAttribute' )
+ ->will( $this->returnValueMap( array( array( 'span', $in ) ) ) );
+
+ $instance = new $this->classUnderTest ( $chameleonTemplate, $domElement );
+
+ $this->assertEquals(
+ "col-lg-$expected",
+ $instance->getClassString()
+ );
+
+ }
+
+ /**
+ * @covers ::getClassString
+ */
+ public function testGetClassString_WithoutSetting() {
+
+ $chameleonTemplate = $this->getMockBuilder( '\Skins\Chameleon\ChameleonTemplate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new $this->classUnderTest ( $chameleonTemplate );
+
+ $this->assertTrue( $instance->getClassString() === 'col-lg-12' );
+
+ }
+
+ public function provideSpanAttributeValues() {
+ return array(
+ array( '9', '9' ),
+ array( '-1', '12' ),
+ array( '42', '12' ),
+ array( 'foo', '12' ),
+ array( '10.5', '12' ),
+ );
+ }
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/ComponentTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/ComponentTest.php
new file mode 100644
index 00000000..a99a0d10
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/ComponentTest.php
@@ -0,0 +1,340 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\Component
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.0
+ * @ingroup Test
+ */
+class ComponentTest extends \PHPUnit_Framework_TestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\Component';
+
+
+ /**
+ * @covers ::__construct
+ */
+ public function testCanConstruct() {
+
+ $chameleonTemplate = $this->getChameleonSkinTemplateStub();
+
+ $instance = $this->getMockForAbstractClass( $this->classUnderTest, array( $chameleonTemplate ) );
+ $instance->expects( $this->any() )
+ ->method( 'getHtml' )
+ ->will( $this->returnValue( 'SomeHtml' ) );
+
+ $this->assertInstanceOf(
+ $this->classUnderTest,
+ $instance
+ );
+
+ $this->assertEquals( 0, $instance->getIndent() );
+ $this->assertNull( $instance->getDomElement() );
+ }
+
+ /**
+ * @covers ::__construct
+ */
+ public function testCanConstruct_withClassAttribute() {
+
+ $chameleonTemplate = $this->getChameleonSkinTemplateStub();
+
+ $domElement = $this->getMockBuilder( '\DOMElement' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $domElement->expects( $this->atLeastOnce() )
+ ->method( 'getAttribute' )
+ ->will( $this->returnValueMap( array( array( 'class', 'someClass' ) ) ) );
+
+ $instance = $this->getMockForAbstractClass( $this->classUnderTest, array( $chameleonTemplate, $domElement ) );
+ $instance->expects( $this->any() )
+ ->method( 'getHtml' )
+ ->will( $this->returnValue( 'SomeHtml' ) );
+
+ $this->assertInstanceOf(
+ $this->classUnderTest,
+ $instance
+ );
+ }
+
+ /**
+ * @covers ::getHtml
+ */
+ public function testGetHtml() {
+
+ $chameleonTemplate = $this->getChameleonSkinTemplateStub();
+
+ $instance = $this->getMockForAbstractClass( $this->classUnderTest, array( $chameleonTemplate ) );
+ $instance->expects( $this->any() )
+ ->method( 'getHtml' )
+ ->will( $this->returnValue( 'SomeHtml' ) );
+
+
+ $this->assertValidHTML( $instance->getHtml() );
+ }
+
+ /**
+ * @covers ::getSkinTemplate
+ */
+ public function testGetSkinTemplate() {
+
+ $chameleonTemplate = $this->getChameleonSkinTemplateStub();
+
+ $instance = $this->getMockForAbstractClass( $this->classUnderTest, array( $chameleonTemplate ) );
+ $instance->expects( $this->any() )
+ ->method( 'getHtml' )
+ ->will( $this->returnValue( 'SomeHtml' ) );
+
+ $this->assertEquals(
+ $chameleonTemplate,
+ $instance->getSkinTemplate()
+ );
+ }
+
+ /**
+ * @covers ::getIndent
+ */
+ public function testGetIndent() {
+
+ $chameleonTemplate = $this->getChameleonSkinTemplateStub();
+
+ $instance = $this->getMockForAbstractClass( $this->classUnderTest, array( $chameleonTemplate, null, 42 ) );
+ $instance->expects( $this->any() )
+ ->method( 'getHtml' )
+ ->will( $this->returnValue( 'SomeHtml' ) );
+
+ $this->assertEquals(
+ 42,
+ $instance->getIndent()
+ );
+ }
+
+ /**
+ * @covers ::indent
+ */
+ public function testIndent() {
+
+ $chameleonTemplate = $this->getChameleonSkinTemplateStub();
+
+ $instance = $this->getMockForAbstractClass( $this->classUnderTest, array( $chameleonTemplate, null, 42 ) );
+ $instance->expects( $this->any() )
+ ->method( 'getHtml' )
+ ->will( $this->returnValue( 'SomeHtml' ) );
+
+ $reflection = new \ReflectionClass( get_class( $instance ) );
+ $method = $reflection->getMethod( 'indent' );
+ $method->setAccessible( true );
+
+ $this->assertEquals(
+ "\n" . str_repeat( "\t", 43 ),
+ $method->invokeArgs( $instance, array( 1 ) )
+ );
+ }
+
+ /**
+ * @covers ::getDomElement
+ */
+ public function testGetDomElement() {
+
+ $chameleonTemplate = $this->getChameleonSkinTemplateStub();
+
+ $domElement = $this->getMockBuilder( '\DOMElement' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = $this->getMockForAbstractClass( $this->classUnderTest, array( $chameleonTemplate, $domElement ) );
+ $instance->expects( $this->any() )
+ ->method( 'getHtml' )
+ ->will( $this->returnValue( 'SomeHtml' ) );
+
+ $this->assertEquals(
+ $domElement,
+ $instance->getDomElement()
+ );
+ }
+
+ /**
+ * @covers ::getClassString
+ */
+ public function testGetClassString_WithoutSetting() {
+
+ $chameleonTemplate = $this->getChameleonSkinTemplateStub();
+
+ $instance = $this->getMockForAbstractClass( $this->classUnderTest, array( $chameleonTemplate ) );
+ $instance->expects( $this->any() )
+ ->method( 'getHtml' )
+ ->will( $this->returnValue( 'SomeHtml' ) );
+
+ $this->assertInternalType( 'string', $instance->getClassString() );
+
+ }
+
+ /**
+ * @covers ::setClasses
+ * @covers ::getClassString
+ * @dataProvider setClassesProvider
+ */
+ public function testSetClasses( $input, $expected ) {
+
+ $chameleonTemplate = $this->getChameleonSkinTemplateStub();
+
+ $instance = $this->getMockForAbstractClass( $this->classUnderTest, array( $chameleonTemplate ) );
+ $instance->expects( $this->any() )
+ ->method( 'getHtml' )
+ ->will( $this->returnValue( 'SomeHtml' ) );
+
+ $instance->setClasses( $input );
+
+ $this->assertEquals( $expected, $instance->getClassString() );
+ }
+
+ /**
+ * @covers ::setClasses
+ * @expectedException \MWException
+ */
+ public function testSetClasses_WithInvalidParameter() {
+
+ $chameleonTemplate = $this->getChameleonSkinTemplateStub();
+
+ $instance = $this->getMockForAbstractClass( $this->classUnderTest, array( $chameleonTemplate ) );
+ $instance->expects( $this->any() )
+ ->method( 'getHtml' )
+ ->will( $this->returnValue( 'SomeHtml' ) );
+
+ $instance->setClasses( true ); // use bool instead of string
+
+ }
+
+ /**
+ * @covers ::addClasses
+ * @covers ::getClassString
+ * @covers ::transformClassesToArray
+ * @dataProvider addClassesProvider
+ */
+ public function testAddClasses( $input1, $input2, $combined ) {
+
+ $chameleonTemplate = $this->getChameleonSkinTemplateStub();
+
+ $instance = $this->getMockForAbstractClass( $this->classUnderTest, array( $chameleonTemplate ) );
+ $instance->expects( $this->any() )
+ ->method( 'getHtml' )
+ ->will( $this->returnValue( 'SomeHtml' ) );
+
+ $instance->setClasses( $input1 );
+ $instance->addClasses( $input2 );
+
+ $this->assertEquals( $combined, $instance->getClassString() );
+ }
+
+ /**
+ * @covers ::removeClasses
+ * @covers ::getClassString
+ * @dataProvider removeClassesProvider
+ */
+ public function testRemoveClasses( $combined, $toRemove, $remainder ) {
+
+ $chameleonTemplate = $this->getChameleonSkinTemplateStub();
+
+ $instance = $this->getMockForAbstractClass( $this->classUnderTest, array( $chameleonTemplate ) );
+ $instance->expects( $this->any() )
+ ->method( 'getHtml' )
+ ->will( $this->returnValue( 'SomeHtml' ) );
+
+ $instance->setClasses( $combined );
+ $instance->removeClasses( $toRemove );
+
+ $this->assertEquals( $remainder, $instance->getClassString() );
+ }
+
+ public function setClassesProvider() {
+ return array(
+ array( null, '' ),
+
+ array( '', '' ),
+ array( array(), '' ),
+
+ array( 'foo bar baz', 'foo bar baz' ),
+ array( array( 'foo', 'bar', 'baz', ), 'foo bar baz' ),
+ );
+ }
+
+ public function addClassesProvider() {
+ return array(
+ array( 'foo bar', null, 'foo bar' ),
+
+ array( 'foo bar', '', 'foo bar' ),
+ array( 'foo bar', array(), 'foo bar' ),
+
+ array( 'foo bar', 'baz', 'foo bar baz' ),
+ array( 'foo bar', array( 'baz' ), 'foo bar baz' ),
+
+ array( 'foo bar', 'baz quok', 'foo bar baz quok' ),
+ array( 'foo bar', array( 'baz', 'quok' ), 'foo bar baz quok' ),
+ );
+ }
+
+ public function removeClassesProvider() {
+ return array(
+ array( 'foo bar', null, 'foo bar' ),
+
+ array( 'foo bar', '', 'foo bar' ),
+ array( 'foo bar', array(), 'foo bar' ),
+
+ array( 'foo bar baz', 'bar', 'foo baz' ),
+ array( 'foo bar baz', array( 'baz' ), 'foo bar' ),
+
+ array( 'foo bar baz quok', 'foo baz', 'bar quok' ),
+ array( 'foo bar baz quok', array( 'bar', 'baz' ), 'foo quok' ),
+ );
+ }
+
+ protected function getChameleonSkinTemplateStub() {
+ return $this->getMockBuilder( '\Skins\Chameleon\ChameleonTemplate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ /**
+ * Asserts that $actual is a valid HTML fragment
+ *
+ * @todo Currently only asserts that $actual is a string. Need to parse and validate,
+ *
+ * @param $actual
+ * @param string $message
+ */
+ public function assertValidHTML( $actual, $message = '' ) {
+ $this->assertInternalType( 'string', $actual, $message );
+ }
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/ContainerTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/ContainerTest.php
new file mode 100644
index 00000000..d33ae07b
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/ContainerTest.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\Container
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class ContainerTest extends GenericComponentTestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\Container';
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/FooterIconsTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/FooterIconsTest.php
new file mode 100644
index 00000000..8cc19bec
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/FooterIconsTest.php
@@ -0,0 +1,85 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\FooterIcons
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class FooterIconsTest extends GenericComponentTestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\FooterIcons';
+
+ /**
+ * @covers ::getHtml
+ */
+ public function testGetHtml() {
+
+ $chameleonTemplate = $this->getChameleonSkinTemplateStub();
+
+ $skin = $chameleonTemplate->getSkin();
+
+ $skin->expects( $this->at( 0 ) )
+ ->method( 'makeFooterIcon' )
+ ->with( $this->equalTo( 'icon1' ) )
+ ->will( $this->returnValue( 'SomeHTML' ) );
+
+ $skin->expects( $this->at( 1 ) )
+ ->method( 'makeFooterIcon' )
+ ->with( $this->equalTo( 'icon2' ) )
+ ->will( $this->returnValue( 'SomeHTML' ) );
+
+ $skin->expects( $this->at( 2 ) )
+ ->method( 'makeFooterIcon' )
+ ->with( $this->equalTo( 'icon3' ) )
+ ->will( $this->returnValue( 'SomeHTML' ) );
+
+ $skin->expects( $this->at( 3 ) )
+ ->method( 'makeFooterIcon' )
+ ->with( $this->equalTo( 'icon4' ) )
+ ->will( $this->returnValue( 'SomeHTML' ) );
+
+ $chameleonTemplate->expects( $this->any() )
+ ->method( 'getFooterIcons' )
+ ->will( $this->returnValue( array(
+ 'block1' => array( 'icon1', 'icon2' ),
+ 'block2' => array( 'icon3', 'icon4' ),
+ ) ) );
+
+ $instance = new $this->classUnderTest ( $chameleonTemplate );
+
+ $this->assertValidHTML( $instance->getHtml() );
+ }
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/FooterInfoTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/FooterInfoTest.php
new file mode 100644
index 00000000..60e97af9
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/FooterInfoTest.php
@@ -0,0 +1,78 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\FooterInfo
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class FooterInfoTest extends GenericComponentTestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\FooterInfo';
+ protected $componentUnderTest = 'FooterInfo';
+
+
+ /**
+ * @covers ::getHtml
+ */
+ public function testGetHtml_GetsAllKeys() {
+
+ $chameleonTemplate = $this->getChameleonSkinTemplateStub();
+
+ $chameleonTemplate->expects( $this->at( 1 ) )
+ ->method( 'get' )
+ ->with( $this->equalTo( 'key1' ), $this->equalTo( null ) )
+ ->will( $this->returnValue( 'SomeHTML' ) );
+
+ $chameleonTemplate->expects( $this->at( 2 ) )
+ ->method( 'get' )
+ ->with( $this->equalTo( 'key2' ), $this->equalTo( null ) )
+ ->will( $this->returnValue( 'SomeHTML' ) );
+
+ $chameleonTemplate->expects( $this->at( 3 ) )
+ ->method( 'get' )
+ ->with( $this->equalTo( 'key3' ), $this->equalTo( null ) )
+ ->will( $this->returnValue( 'SomeHTML' ) );
+
+ $chameleonTemplate->expects( $this->at( 4 ) )
+ ->method( 'get' )
+ ->with( $this->equalTo( 'key4' ), $this->equalTo( null ) )
+ ->will( $this->returnValue( 'SomeHTML' ) );
+
+ $instance = new $this->classUnderTest ( $chameleonTemplate );
+
+ $instance->getHtml();
+ }
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/FooterPlacesTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/FooterPlacesTest.php
new file mode 100644
index 00000000..f25cc53d
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/FooterPlacesTest.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\FooterPlaces
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class FooterPlacesTest extends GenericComponentTestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\FooterPlaces';
+
+ /**
+ * @covers ::getHtml
+ */
+ public function testGetHtml_GetsAllKeys() {
+
+ $chameleonTemplate = $this->getChameleonSkinTemplateStub();
+
+ $chameleonTemplate->expects( $this->at( 1 ) )
+ ->method( 'get' )
+ ->with( $this->equalTo( 'privacy' ), $this->equalTo( null ) )
+ ->will( $this->returnValue( 'SomeHTML' ) );
+
+ $chameleonTemplate->expects( $this->at( 2 ) )
+ ->method( 'get' )
+ ->with( $this->equalTo( 'about' ), $this->equalTo( null ) )
+ ->will( $this->returnValue( 'SomeHTML' ) );
+
+ $chameleonTemplate->expects( $this->at( 3 ) )
+ ->method( 'get' )
+ ->with( $this->equalTo( 'disclaimer' ), $this->equalTo( null ) )
+ ->will( $this->returnValue( 'SomeHTML' ) );
+
+ $instance = new $this->classUnderTest ( $chameleonTemplate );
+
+ $instance->getHtml();
+
+ }
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/GenericComponentTestCase.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/GenericComponentTestCase.php
new file mode 100644
index 00000000..9d3417bd
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/GenericComponentTestCase.php
@@ -0,0 +1,345 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components;
+
+use DOMDocument;
+use DOMXPath;
+use Skins\Chameleon\Components\Component;
+use Skins\Chameleon\Tests\Util\DocumentElementFinder;
+use Skins\Chameleon\Tests\Util\MockupFactory;
+use Skins\Chameleon\Tests\Util\XmlFileProvider;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\Component
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class GenericComponentTestCase extends \PHPUnit_Framework_TestCase {
+
+ private $successColor = '';
+ private $testObject;
+ protected $classUnderTest;
+ protected $componentUnderTest;
+
+ private static $lastValidatorCallTime = 0;
+
+ /**
+ * @covers ::__construct
+ */
+ public function testCanConstruct() {
+
+ /** @var $instance Component */
+ $instance = $this->getTestObject();
+
+ $this->assertInstanceOf(
+ $this->classUnderTest,
+ $instance
+ );
+
+ $this->assertEquals( 0, $instance->getIndent() );
+ $this->assertNull( $instance->getDomElement() );
+ }
+
+ /**
+ * @covers ::getHtml
+ */
+ public function testGetHtml_withEmptyElement() {
+
+ /** @var $instance Component */
+ $instance = $this->getTestObject();
+ $this->assertValidHTML( $instance->getHtml() );
+ }
+
+ /**
+ * @covers ::getHtml
+ * @dataProvider domElementProviderFromSyntheticLayoutFiles
+ *
+ * @param \DOMElement $domElement
+ */
+ public function testGetHtml_OnSyntheticLayoutXml( \DOMElement $domElement ) {
+
+ /** @var $instance Component */
+ $instance = $this->getTestObject( $domElement );
+ $this->assertValidHTML( $instance->getHtml() );
+ }
+
+ /**
+ * @covers ::getHtml
+ * @dataProvider domElementProviderFromDeployedLayoutFiles
+ */
+ public function testGetHtml_OnDeployedLayoutXml( $domElement ) {
+
+ if ( $domElement === null ) {
+ $this->assertTrue( true );
+ return;
+ }
+
+ /** @var $instance Component */
+ $instance = $this->getTestObject( $domElement );
+
+ $this->assertValidHTML( $instance->getHtml() );
+ }
+
+ public function getTestObject( \DOMElement $domElement = null ) {
+ if ( $this->testObject === null ) {
+ $chameleonTemplate = $this->getChameleonSkinTemplateStub();
+ $this->testObject = new $this->classUnderTest ( $chameleonTemplate, $domElement );
+ }
+ return $this->testObject;
+ }
+
+ public function domElementProviderFromSyntheticLayoutFiles() {
+ $file = __DIR__ . '/../../Fixture/' . $this->getNameOfComponentUnderTest() . '.xml';
+ $provider = array_chunk( $this->getDomElementsFromFile( $file ), 1 );
+ return $provider;
+ }
+
+ public function domElementProviderFromDeployedLayoutFiles() {
+
+ $xmlFileProvider = new XmlFileProvider( __DIR__ . '/../../../../layouts' );
+ $files = $xmlFileProvider->getFiles();
+
+ $elements = array();
+ foreach ( $files as $file ) {
+ $elements = array_merge( $elements, $this->getDomElementsFromFile( $file ) );
+ }
+
+ if ( count( $elements ) === 0 ) {
+ $elements[ ] = null;
+ }
+
+ $provider = array_chunk( $elements, 1 );
+
+ return $provider;
+ }
+
+ protected function getDomElementsFromFile( $file ) {
+ $elementFinder = new DocumentElementFinder( $file );
+ $nameParts = array_values( explode( '\\', $this->getNameOfComponentUnderTest() ) );
+ $componentName = end( $nameParts );
+ return $elementFinder->getComponentsByTypeAttribute( $componentName );
+ }
+
+ protected static function loadXML( $fragment, $isHtml = true ) {
+
+ if ( $isHtml ) {
+ $fragment = self::wrapHtmlFragment( $fragment );
+ }
+
+ $doc = new DOMDocument();
+ $doc->preserveWhiteSpace = false;
+
+ if ( $isHtml === true ) {
+ libxml_use_internal_errors( true );
+ $result = $doc->loadHTML( $fragment );
+ libxml_use_internal_errors( false );
+ } else {
+ $result = $doc->loadXML( $fragment );
+ }
+
+ if ( $result === true ) {
+ return $doc;
+ } else {
+ return false;
+ }
+
+ }
+
+ protected static function wrapHtmlFragment( $fragment ) {
+ return '<!DOCTYPE html><html><head><meta charset="utf-8" /><title>SomeTitle</title></head><body>' . $fragment . '</body></html>';
+ }
+
+ /**
+ * Evaluate an HTML or XML string and assert its structure and/or contents.
+ *
+ * @todo: Currently only supports 'tag' and 'class'
+ *
+ * The first argument ($matcher) is an associative array that specifies the
+ * match criteria for the assertion:
+ *
+ * - `id` : the node with the given id attribute must match the
+ * corresponding value.
+ * - `tag` : the node type must match the corresponding value.
+ * - `attributes` : a hash. The node's attributes must match the
+ * corresponding values in the hash.
+ * - `class` : The node's class attribute must contain the given
+ * value.
+ * - `content` : The text content must match the given value.
+ * - `parent` : a hash. The node's parent must match the
+ * corresponding hash.
+ * - `child` : a hash. At least one of the node's immediate children
+ * must meet the criteria described by the hash.
+ * - `ancestor` : a hash. At least one of the node's ancestors must
+ * meet the criteria described by the hash.
+ * - `descendant` : a hash. At least one of the node's descendants must
+ * meet the criteria described by the hash.
+ * - `children` : a hash, for counting children of a node.
+ * Accepts the keys:
+ * - `count` : a number which must equal the number of children
+ * that match
+ * - `less_than` : the number of matching children must be greater
+ * than this number
+ * - `greater_than` : the number of matching children must be less than
+ * this number
+ * - `only` : another hash consisting of the keys to use to match
+ * on the children, and only matching children will be
+ * counted
+ *
+ * @param array $matcher
+ * @param string $actual
+ * @param string $message
+ * @param bool $isHtml
+ */
+ public static function assertTag( $matcher, $actual, $message = 'Failed asserting that the given fragment contained the described node.', $isHtml = true ) {
+
+ $doc = self::loadXML( $actual, $isHtml );
+
+ if ( $doc === false ) {
+ self::fail( $message );
+ }
+
+ $query = '//';
+
+ if ( array_key_exists( 'tag', $matcher ) ) {
+ $query .= strtolower( $matcher[ 'tag' ] );
+ unset( $matcher[ 'tag' ] );
+ } else {
+ $query .= '*';
+ }
+
+ if ( array_key_exists( 'class', $matcher ) ) {
+ $query .= '[contains(concat(" ", normalize-space(@class), " "), " ' . $matcher[ 'class' ] . ' ")]';
+ unset( $matcher[ 'class' ] );
+ }
+
+ if ( count( $matcher ) > 0 ) {
+ trigger_error( 'Found unsupported matcher tags: ' . implode( ', ', array_keys( $matcher ) ), E_USER_WARNING );
+ }
+
+ $xpath = new DOMXPath( $doc );
+ $entries = $xpath->query( $query );
+
+ self::assertGreaterThan( 0, $entries->length, $message );
+
+ }
+
+ /**
+ * Asserts that $actual is a valid HTML fragment
+ *
+ * @todo Put this whole stuff in a \PHPUnit_Framework_Constraint and just call assertThat
+ *
+ * @param $actual
+ * @param string $message
+ */
+ public function assertValidHTML( $actual, $message = 'HTML text is not valid. ' ) {
+
+ if ( !USE_EXTERNAL_HTML_VALIDATOR ) {
+
+ $doc = $this->loadXML( $actual, true );
+ $this->assertNotFalse( $doc, $message );
+
+ return;
+ }
+
+ $actual = $this->wrapHtmlFragment( $actual );
+
+ $curlVersion = curl_version();
+
+ // cURL
+ $curl = curl_init();
+
+ curl_setopt_array( $curl, array(
+ CURLOPT_CONNECTTIMEOUT => 1,
+ CURLOPT_URL => 'http://validator.w3.org/check',
+ CURLOPT_USERAGENT => 'cURL ' . $curlVersion[ 'version' ],
+ CURLOPT_RETURNTRANSFER => true,
+ CURLOPT_POST => true,
+ CURLOPT_POSTFIELDS => array(
+ 'output' => 'json',
+ 'fragment' => $actual,
+ ),
+ ) );
+
+ @time_sleep_until( self::$lastValidatorCallTime + 1 );
+ self::$lastValidatorCallTime = time();
+
+ $response = curl_exec( $curl );
+ $curlInfo = curl_getinfo( $curl );
+
+ curl_close( $curl );
+
+ if ( $response === false ) {
+ $this->markTestIncomplete( 'Could not connect to validation service.' );
+ }
+
+ if ( $curlInfo[ 'http_code' ] != '200' ) {
+ $this->markTestIncomplete( 'Error connecting to validation service. HTTP ' . $curlInfo[ 'http_code' ] );
+ }
+
+ $response = json_decode( $response, true );
+
+ if ( $response === null ) {
+ $this->markTestIncomplete( 'Validation service returned an invalid response (invalid JSON): ' . $response );
+ }
+
+ // fail if errors or warnings
+ if ( array_key_exists( 'messages', $response ) ) {
+
+ foreach ( $response[ 'messages' ] as $responseMessage ) {
+
+ if ( $responseMessage[ 'type' ] === 'error' || $responseMessage[ 'type' ] === 'warning' ) {
+ $this->fail( $message . ucfirst( $response[ 'messages' ][ 0 ][ 'type' ] ) . ': ' . $response[ 'messages' ][ 0 ][ 'message' ] );
+ }
+
+ }
+ }
+
+ // valid
+ $this->successColor = 'bg-green,fg-black';
+ $this->assertTrue( true );
+
+ }
+
+ public function getChameleonSkinTemplateStub() {
+ return MockupFactory::makeFactory( $this )->getChameleonSkinTemplateStub();
+ }
+
+ public function getSuccessColor() {
+ return $this->successColor;
+ }
+
+ public function getNameOfComponentUnderTest() {
+ return str_replace( 'Skins\\Chameleon\\Components\\', '', get_class( $this->getTestObject() ) );
+ }
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/GridTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/GridTest.php
new file mode 100644
index 00000000..bd149f2b
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/GridTest.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\Grid
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class GridTest extends GenericComponentTestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\Grid';
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/HtmlTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/HtmlTest.php
new file mode 100644
index 00000000..1c7fb0df
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/HtmlTest.php
@@ -0,0 +1,67 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components;
+
+use Skins\Chameleon\Components\Html;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\Html
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class HtmlTest extends GenericComponentTestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\Html';
+
+ /**
+ * @covers ::getHtml
+ * @dataProvider domElementProviderFromSyntheticLayoutFiles
+ *
+ * @param \DOMElement $domElement
+ */
+ public function testGetHtml_OnSyntheticLayoutXml( \DOMElement $domElement ) {
+
+ $chameleonTemplate = $this->getChameleonSkinTemplateStub();
+
+ $expected = '';
+
+ foreach ( $domElement->childNodes as $child ) {
+ $expected .= $domElement->ownerDocument->saveHTML( $child );
+ }
+
+ $instance = new Html ( $chameleonTemplate, $domElement );
+ $actual = $instance->getHtml();
+
+ $this->assertEquals( $expected, $actual );
+ }
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/LogoTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/LogoTest.php
new file mode 100644
index 00000000..bac0e03a
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/LogoTest.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\Logo
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class LogoTest extends GenericComponentTestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\Logo';
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/MainContentTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/MainContentTest.php
new file mode 100644
index 00000000..86398fb6
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/MainContentTest.php
@@ -0,0 +1,63 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke, mwjames
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components;
+
+use Skins\Chameleon\Components\MainContent;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\MainContent
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author mwjames
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class MainContentTest extends GenericComponentTestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\MainContent';
+
+ /**
+ * @covers ::getHtml
+ */
+ public function testGetHtml_OnEmptyDataProperty() {
+
+ $chameleonTemplate = $this->getChameleonSkinTemplateStub();
+
+ $chameleonTemplate->data = array(
+ 'subtitle' => '',
+ 'undelete' => '',
+ 'printfooter' => '',
+ 'dataAfterContent' => ''
+ );
+
+ $instance = new MainContent( $chameleonTemplate );
+ $this->assertInternalType( 'string', $instance->getHtml() );
+ }
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/MenuTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/MenuTest.php
new file mode 100644
index 00000000..e9aaaa92
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/MenuTest.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\Menu
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class MenuTest extends GenericComponentTestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\Menu';
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/Modifications/GenericModificationTestCase.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/Modifications/GenericModificationTestCase.php
new file mode 100644
index 00000000..a7b76cc2
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/Modifications/GenericModificationTestCase.php
@@ -0,0 +1,57 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components\Modifications;
+use Skins\Chameleon\Components\Component;
+use Skins\Chameleon\Components\Silent;
+use Skins\Chameleon\Tests\Unit\Components\GenericComponentTestCase;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\Modifications\Modification
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.1
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class GenericModificationTestCase extends GenericComponentTestCase {
+
+ public function getTestObject( \DOMElement $domElement = null ) {
+ $component = $this->getModifiedComponent();
+ return new $this->classUnderTest ( $component, $domElement );
+ }
+
+ /**
+ * @return Component
+ */
+ protected function getModifiedComponent() {
+ $chameleonTemplate = $this->getChameleonSkinTemplateStub();
+ return new Silent( $chameleonTemplate );
+ }
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/Modifications/HideForTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/Modifications/HideForTest.php
new file mode 100644
index 00000000..a9369b7c
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/Modifications/HideForTest.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components\Modifications;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\Modifications\HideFor
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.1
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class HideForTest extends GenericModificationTestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\Modifications\HideFor';
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/Modifications/ShowOnlyForTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/Modifications/ShowOnlyForTest.php
new file mode 100644
index 00000000..928a89f7
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/Modifications/ShowOnlyForTest.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components\Modifications;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\Modifications\ShowOnlyFor
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.1
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class ShowOnlyTest extends GenericModificationTestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\Modifications\ShowOnlyFor';
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/NavMenuTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/NavMenuTest.php
new file mode 100644
index 00000000..cec2a6a6
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/NavMenuTest.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\NavMenu
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class NavMenuTest extends GenericComponentTestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\NavMenu';
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/NavbarHorizontalTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/NavbarHorizontalTest.php
new file mode 100644
index 00000000..2f35b00e
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/NavbarHorizontalTest.php
@@ -0,0 +1,78 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke, mwjames
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components;
+
+use Skins\Chameleon\Components\NavbarHorizontal;
+use Skins\Chameleon\Tests\Util\MockupFactory;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\NavbarHorizontal
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author mwjames
+ * @author Stephan Gambke
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class NavbarHorizontalTest extends GenericComponentTestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\NavbarHorizontal';
+
+ /**
+ * @covers ::getHtml
+ */
+ public function testGetHtml_containsNavElement() {
+
+ $element = $this->getMockBuilder( '\DOMElement' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $message = $this->getMockBuilder( '\Message' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $chameleonTemplate = $this->getMockBuilder( '\Skins\Chameleon\ChameleonTemplate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $chameleonTemplate->expects( $this->any() )
+ ->method( 'getMsg' )
+ ->will( $this->returnValue( $message ) );
+
+ $instance = new NavbarHorizontal(
+ $chameleonTemplate,
+ $element
+ );
+
+ $matcher = array( 'tag' => 'nav' );
+ $this->assertTag( $matcher, $instance->getHtml() );
+ }
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/NavbarHorizontral/PageToolsAdaptableTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/NavbarHorizontral/PageToolsAdaptableTest.php
new file mode 100644
index 00000000..424e403c
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/NavbarHorizontral/PageToolsAdaptableTest.php
@@ -0,0 +1,326 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2017, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components\NavbarHorizontal;
+
+use Skins\Chameleon\Components\NavbarHorizontal\PageToolsAdaptable;
+use Skins\Chameleon\Tests\Unit\Components\GenericComponentTestCase;
+use \Html;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\NavbarHorizontal\PageToolsAdaptable
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.6
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class PageToolsAdaptableTest extends GenericComponentTestCase
+{
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\NavbarHorizontal\PageToolsAdaptable';
+
+ /**
+ * @param string $show
+ * @param array $expectedIconClasses
+ * @covers ::getHtml
+ * @dataProvider providerShowIconData
+ */
+ public function testGetHtml_ContainsIconsToShow( $show, $expectedIconClasses ) {
+
+ $chameleonTemplate = $this->getMockBuilder( '\Skins\Chameleon\ChameleonTemplate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $chameleonTemplate->expects( $this->any() )
+ ->method( 'get' )
+ ->will( $this->returnValue( $this->skinTemplateGet() ) );
+
+ $message = $this->getMockBuilder( '\Message' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $message->expects( $this->any() )
+ ->method( 'text' )
+ ->will( $this->returnValue( '' ) );
+
+ $chameleonTemplate->method( 'getMsg' )
+ ->willReturn( $message );
+
+ $chameleonTemplate->method( 'makeListItem' )
+ ->will( $this->returnCallback( array( $this, 'makeListItem' ) ) );
+
+ $domElement = $this->getMockBuilder( '\DOMElement' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $domElement->expects( $this->any() )
+ ->method( 'getAttribute' )
+ ->will( $this->returnValue( $show ) );
+
+ /** @var \Skins\Chameleon\Components\Component $instance */
+ $instance = new $this->classUnderTest ( $chameleonTemplate, $domElement );
+
+ $output = $instance->getHtml();
+ foreach ( $expectedIconClasses as $expectedIconClass ) {
+ $matcher = array( 'tag' => 'span', 'class' => $expectedIconClass );
+ $this->assertTag(
+ $matcher,
+ $output,
+ 'Failed asserting that the given fragment contained the described node. '
+ . 'Class "' . $expectedIconClass . '" not found in output for show value "' . $show . '"!'
+ );
+ }
+ }
+
+ /**
+ * @covers ::getHtml
+ */
+ public function testGetHtml_ContainsNoIconsOnEmptyShow() {
+
+ $chameleonTemplate = $this->getMockBuilder( '\Skins\Chameleon\ChameleonTemplate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $chameleonTemplate->expects( $this->any() )
+ ->method( 'get' )
+ ->will( $this->returnValue( $this->skinTemplateGet() ) );
+
+ $message = $this->getMockBuilder( '\Message' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $message->expects( $this->any() )
+ ->method( 'text' )
+ ->will( $this->returnValue( '' ) );
+
+ $chameleonTemplate->method( 'getMsg' )
+ ->willReturn( $message );
+
+ $chameleonTemplate->method( 'makeListItem' )
+ ->will( $this->returnCallback( array( $this, 'makeListItem' ) ) );
+
+ $domElement = $this->getMockBuilder( '\DOMElement' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $domElement->expects( $this->any() )
+ ->method( 'getAttribute' )
+ ->will( $this->returnValue( '' ) );
+
+ /** @var \Skins\Chameleon\Components\Component $instance */
+ $instance = new $this->classUnderTest ( $chameleonTemplate, $domElement );
+
+ $output = $instance->getHtml();
+ $this->assertNotContains(
+ 'glyphicon glyphicon-',
+ $output
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function providerShowIconData() {
+ return array(
+ 'view only' => array(
+ 'view',
+ array( 'glyphicon glyphicon-' . PageToolsAdaptable::getGlyphIconForAction( 'view' ) ),
+ ),
+ 'all edits' => array(
+ 'edit,ve-edit,formedit',
+ array(
+ 'glyphicon glyphicon-' . PageToolsAdaptable::getGlyphIconForAction( 'edit' ),
+ 'glyphicon glyphicon-' . PageToolsAdaptable::getGlyphIconForAction( 've-edit' ),
+ 'glyphicon glyphicon-' . PageToolsAdaptable::getGlyphIconForAction( 'formedit' ),
+ ),
+ ),
+ 'some invalid' => array(
+ 'view,etit,history,wotch,protekt',
+ array(
+ 'glyphicon glyphicon-' . PageToolsAdaptable::getGlyphIconForAction( 'view' ),
+ 'glyphicon glyphicon-' . PageToolsAdaptable::getGlyphIconForAction( 'history' ),
+ ),
+ ),
+ );
+ }
+
+ /**
+ * @param string $key
+ * @param array $item
+ * @param array $options
+ * @return string
+ */
+ public function makeListItem( $key, $item, $options = array() ) {
+ $html = isset( $item['text'] ) ? htmlentities( $item['text'] ) : '';
+ if ( isset( $options['text-wrapper'] ) ) {
+ $wrapper = $options['text-wrapper'];
+ $html = Html::rawElement( $wrapper['tag'], $wrapper['attributes'], $html );
+ }
+
+ $link = $item;
+ // These keys are used by makeListItem and shouldn't be passed on to the link
+ foreach ( array( 'id', 'class', 'active', 'tag', 'itemtitle' ) as $k ) {
+ unset( $link[$k] );
+ }
+ if ( isset( $options['link-class'] ) ) {
+ if ( isset( $link['class'] ) ) {
+ $link['class'] .= " {$options['link-class']}";
+ } else {
+ $link['class'] = $options['link-class'];
+ }
+ }
+ $html = Html::rawElement( 'a', $link, $html );
+
+ $attributes = array();
+ foreach ( array( 'id', 'class' ) as $attr ) {
+ if ( isset( $item[$attr] ) ) {
+ $attributes[$attr] = $item[$attr];
+ }
+ }
+ if ( isset( $item['active'] ) && $item['active'] ) {
+ if ( !isset( $attributes['class'] ) ) {
+ $attributes['class'] = '';
+ }
+ $attributes['class'] .= ' active';
+ $attributes['class'] = trim( $attributes['class'] );
+ }
+ if ( isset( $item['itemtitle'] ) ) {
+ $attributes['title'] = $item['itemtitle'];
+ }
+ return Html::rawElement( isset( $options['tag'] ) ? $options['tag'] : 'li', $attributes, $html );
+ }
+
+ /**
+ * @return array
+ */
+ private function skinTemplateGet() {
+ return array(
+ 'namespaces' => array(
+ 'talk' => array(
+ 'class' => '',
+ 'text' => 'Discussion',
+ 'href' => '/mw/index.php?title=Talk:Main_Page',
+ 'primary' => true,
+ 'context' => 'talk',
+ 'id' => 'ca-talk',
+ ),
+ ),
+ 'views' => array(
+ 'view' => array(
+ 'class' => 'selected',
+ 'text' => 'View',
+ 'href' => '/mw/index.php/Main_Page',
+ 'primary' => true,
+ 'redundant' => true,
+ 'id' => 'ca-view',
+ ),
+ 've-edit' => array(
+ 'class' => '',
+ 'text' => 'Edit with Virtual Editor',
+ 'href' => '/mw/index.php?title=Main_Page&veaction=edit',
+ 'primary' => true,
+ 'id' => 'ca-ve-edit',
+ ),
+ 'edit' => array(
+ 'class' => 'collapsible',
+ 'text' => 'Edit',
+ 'href' => '/mw/index.php?title=Main_Page&action=edit',
+ 'primary' => true,
+ 'id' => 'ca-edit',
+ ),
+ 'formedit' => array(
+ 'class' => '',
+ 'text' => 'Edit with PageForms',
+ 'href' => '/mw/index.php?title=Main_Page&action=formedit',
+ 'primary' => true,
+ 'id' => 'ca-formedit',
+ ),
+ 'history' => array(
+ 'class' => '',
+ 'text' => 'History',
+ 'href' => '/mw/index.php?title=Main_Page&action=history',
+ 'rel' => 'archives',
+ 'id' => 'ca-history',
+ ),
+ ),
+ 'actions' => array(
+ 'delete' => array(
+ 'class' => '',
+ 'text' => 'Delete',
+ 'href' => '/mw/index.php?title=Main_Page&action=delete',
+ 'id' => 'ca-delete',
+ ),
+ 'undelete' => array(
+ 'class' => '',
+ 'text' => 'Restore 1 Version',
+ 'href' => '/mw/index.php?title=Special:Undelete/Main_Page',
+ 'id' => 'ca-undelete',
+ ),
+ 'move' => array(
+ 'class' => '',
+ 'text' => 'Move',
+ 'href' => '/mw/index.php?title=Special:Move/Main_Page',
+ 'id' => 'ca-move',
+ ),
+ 'protect' => array(
+ 'class' => '',
+ 'text' => 'Protect',
+ 'href' => '/mw/index.php?title=Main_Page&action=protect',
+ 'id' => 'ca-protect',
+ ),
+ 'unprotect' => array(
+ 'class' => '',
+ 'text' => 'Change Protection',
+ 'href' => '/mw/index.php?title=Main_Page&action=unprotect',
+ 'id' => 'ca-unprotect',
+ ),
+ 'watch' => array(
+ 'class' => 'mw-watchlink',
+ 'text' => 'Watch',
+ 'href' => '/mw/index.php?title=Main_Page&action=watch',
+ 'id' => 'ca-watch',
+ ),
+ 'unwatch' => array(
+ 'class' => 'mw-watchlink',
+ 'text' => 'Unwatch',
+ 'href' => '/mw/index.php?title=Main_Page&action=unwatch',
+ 'id' => 'ca-unwatch',
+ ),
+ 'purge' => array(
+ 'class' => '',
+ 'text' => 'Refresh',
+ 'href' => '/mw/index.php?title=Main_Page&action=purge',
+ 'id' => 'ca-purge',
+ ),
+ ),
+ 'variants' => array(),
+ );
+ }
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/NavbarHorizontral/PersonalToolsTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/NavbarHorizontral/PersonalToolsTest.php
new file mode 100644
index 00000000..3de3dc0b
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/NavbarHorizontral/PersonalToolsTest.php
@@ -0,0 +1,84 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2017, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components\NavbarHorizontal;
+
+use Skins\Chameleon\Tests\Unit\Components\GenericComponentTestCase;
+use Skins\Chameleon\Tests\Util\MockupFactory;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\NavbarHorizontal\PersonalTools
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.6
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class PersonalToolsTest extends GenericComponentTestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\NavbarHorizontal\PersonalTools';
+
+ /**
+ * @covers ::getHtml
+ * @dataProvider domElementProviderFromSyntheticLayoutFiles
+ */
+ public function testGetHtml_LoggedInUserHasNewMessages( $domElement ) {
+
+ $factory = MockupFactory::makeFactory( $this );
+ $factory->set( 'UserIsLoggedIn', true );
+ $factory->set( 'UserNewMessageLinks', array( 'foo' ) );
+ $chameleonTemplate = $factory->getChameleonSkinTemplateStub();
+
+ /** @var \Skins\Chameleon\Components\Component $instance */
+ $instance = new $this->classUnderTest ( $chameleonTemplate, $domElement );
+
+ $matcher = array( 'class' => 'navbar-newtalk-available' );
+ $this->assertTag( $matcher, $instance->getHtml() );
+ }
+
+ /**
+ * @covers ::getHtml
+ * @dataProvider domElementProviderFromSyntheticLayoutFiles
+ */
+ public function testGetHtml_LoggedInUserHasNoNewMessages( $domElement ) {
+
+ $factory = MockupFactory::makeFactory( $this );
+ $factory->set( 'UserIsLoggedIn', true );
+ $factory->set( 'UserNewMessageLinks', array() );
+ $chameleonTemplate = $factory->getChameleonSkinTemplateStub();
+
+ /** @var \Skins\Chameleon\Components\Component $instance */
+ $instance = new $this->classUnderTest ( $chameleonTemplate, $domElement );
+
+ $matcher = array( 'class' => 'navbar-newtalk-not-available' );
+ $this->assertTag( $matcher, $instance->getHtml() );
+ }
+
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/NewtalkNotifierTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/NewtalkNotifierTest.php
new file mode 100644
index 00000000..8668ff01
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/NewtalkNotifierTest.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\NewtalkNotifier
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class NewtalkNotifierTest extends GenericComponentTestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\NewtalkNotifier';
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/PageToolsTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/PageToolsTest.php
new file mode 100644
index 00000000..410671ae
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/PageToolsTest.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\PageTools
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class PageToolsTest extends GenericComponentTestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\PageTools';
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/PersonalToolsTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/PersonalToolsTest.php
new file mode 100644
index 00000000..cd823979
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/PersonalToolsTest.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\PersonalTools
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class PersonalToolsTest extends GenericComponentTestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\PersonalTools';
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/RowTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/RowTest.php
new file mode 100644
index 00000000..6d7fc6a0
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/RowTest.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\Row
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class RowTest extends GenericComponentTestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\Row';
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/SearchBarTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/SearchBarTest.php
new file mode 100644
index 00000000..86624270
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/SearchBarTest.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\SearchBar
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class SearchBarTest extends GenericComponentTestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\SearchBar';
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/SilentTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/SilentTest.php
new file mode 100644
index 00000000..2906975b
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/SilentTest.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\Silent
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.1
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class SilentTest extends GenericComponentTestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\Silent';
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/SiteNoticeTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/SiteNoticeTest.php
new file mode 100644
index 00000000..d017c213
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/SiteNoticeTest.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\SiteNotice
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class SiteNoticeTest extends GenericComponentTestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\SiteNotice';
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/StructureTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/StructureTest.php
new file mode 100644
index 00000000..9435fd40
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/StructureTest.php
@@ -0,0 +1,57 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\Structure
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class StructureTest extends GenericComponentTestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\Structure';
+// protected $componentUnderTest = 'Structure';
+
+// /**
+// * @covers ::getHtml
+// */
+// public function testGetHtml() {
+//
+// $chameleonTemplate = $this->getChameleonSkinTemplateStub();
+//
+// $instance = new $this->classUnderTest ( $chameleonTemplate );
+//
+// $this->assertTrue( is_string( $instance->getHtml() ) );
+// }
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/ToolbarHorizontalTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/ToolbarHorizontalTest.php
new file mode 100644
index 00000000..57cc1e0f
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Components/ToolbarHorizontalTest.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Components;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Components\ToolbarHorizontal
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class ToolbarHorizontalTest extends GenericComponentTestCase {
+
+ protected $classUnderTest = '\Skins\Chameleon\Components\ToolbarHorizontal';
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Hooks/SetupAfterCacheTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Hooks/SetupAfterCacheTest.php
new file mode 100644
index 00000000..958568a5
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Hooks/SetupAfterCacheTest.php
@@ -0,0 +1,498 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2016, Stephan Gambke, mwjames
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Hooks;
+
+use Skins\Chameleon\Hooks\SetupAfterCache;
+
+/**
+ * @coversDefaultClass \Skins\Chameleon\Hooks\SetupAfterCache
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group skins-chameleon-unit
+ * @group mediawiki-databaseless
+ *
+ * @author mwjames
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class SetupAfterCacheTest extends \PHPUnit_Framework_TestCase {
+
+ protected $dummyExternalModule = null;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->dummyExternalModule = __DIR__ . '/../../Fixture/externalmodule.less';
+ }
+
+ /**
+ * @return string
+ */
+ private function getWorkDirectory() {
+
+ $directory = $GLOBALS[ 'argv' ][ 0 ];
+
+ if ( $directory[ 0 ] !== DIRECTORY_SEPARATOR ) {
+ $directory = $_SERVER[ 'PWD' ] . DIRECTORY_SEPARATOR . $directory;
+ }
+
+ $directory = dirname( $directory );
+
+ return $directory;
+ }
+
+ /**
+ * @covers ::__construct
+ */
+ public function testCanConstruct() {
+
+ $bootstrapManager = $this->getMockBuilder( '\Bootstrap\BootstrapManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $configuration = array();
+
+ $request = $this->getMockBuilder('\WebRequest')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\Skins\Chameleon\Hooks\SetupAfterCache',
+ new SetupAfterCache( $bootstrapManager, $configuration, $request )
+ );
+ }
+
+ /**
+ * @covers ::process
+ * @covers ::registerCommonBootstrapModules
+ * @covers ::registerExternalLessModules
+ */
+ public function testProcessWithValidExternalModuleWithoutLessVariables() {
+
+ $bootstrapManager = $this->getMockBuilder( '\Bootstrap\BootstrapManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $bootstrapManager->expects( $this->at( 1 ) )
+ ->method( 'addExternalModule' );
+
+ $bootstrapManager->expects( $this->at( 2 ) )
+ ->method( 'addExternalModule' )
+ ->with(
+ $this->equalTo( $this->dummyExternalModule ),
+ $this->equalTo( '' ) );
+
+ $bootstrapManager->expects( $this->at( 3 ) )
+ ->method( 'addExternalModule' )
+ ->with(
+ $this->equalTo( $this->dummyExternalModule ),
+ $this->equalTo( 'someRemoteWeDontCheck' ) );
+
+ $bootstrapManager->expects( $this->never() )
+ ->method( 'setLessVariable' );
+
+ $mixedExternalStyleModules = array(
+ $this->dummyExternalModule,
+ $this->dummyExternalModule => 'someRemoteWeDontCheck'
+ );
+
+ $configuration = array(
+ 'egChameleonExternalStyleModules' => $mixedExternalStyleModules,
+ 'IP' => 'notTestingIP',
+ 'wgScriptPath' => 'notTestingwgScriptPath',
+ 'wgStyleDirectory' => 'notTestingwgStyleDirectory',
+ 'wgStylePath' => 'notTestingwgStylePath',
+ );
+
+ $request = $this->getMockBuilder('\WebRequest')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new SetupAfterCache(
+ $bootstrapManager,
+ $configuration,
+ $request
+ );
+
+ $instance->process();
+ }
+
+ /**
+ * @covers ::process
+ * @covers ::registerExternalLessModules
+ */
+ public function testProcessWithInvalidExternalModuleThrowsException() {
+
+ $bootstrapManager = $this->getMockBuilder( '\Bootstrap\BootstrapManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $bootstrapManager->expects( $this->atLeastOnce() )
+ ->method( 'addExternalModule' )
+ ->will( $this->returnValue( true ) );
+
+ $externalStyleModules = array(
+ __DIR__ . '/../../Util/Fixture/' . 'externalmoduleDoesNotExist.less'
+ );
+
+ $configuration = array(
+ 'egChameleonExternalStyleModules' => $externalStyleModules,
+ 'IP' => 'notTestingIP',
+ 'wgScriptPath' => 'notTestingwgScriptPath',
+ 'wgStyleDirectory' => 'notTestingwgStyleDirectory',
+ 'wgStylePath' => 'notTestingwgStylePath'
+ );
+
+ $request = $this->getMockBuilder('\WebRequest')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new SetupAfterCache(
+ $bootstrapManager,
+ $configuration,
+ $request
+ );
+
+ $this->setExpectedException( 'RuntimeException' );
+
+ $instance->process();
+ }
+
+ /**
+ * @covers ::process
+ * @covers ::registerExternalLessVariables
+ */
+ public function testProcessWithLessVariables() {
+
+ $bootstrapManager = $this->getMockBuilder( '\Bootstrap\BootstrapManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $bootstrapManager->expects( $this->once() )
+ ->method( 'addExternalModule' )
+ ->will( $this->returnValue( true ) );
+
+ $bootstrapManager->expects( $this->once() )
+ ->method( 'setLessVariable' )
+ ->with(
+ $this->equalTo( 'foo' ),
+ $this->equalTo( '999px' ) );
+
+ $externalLessVariables = array(
+ 'foo' => '999px'
+ );
+
+ $configuration = array(
+ 'egChameleonExternalLessVariables' => $externalLessVariables,
+ 'IP' => 'notTestingIP',
+ 'wgScriptPath' => 'notTestingwgScriptPath',
+ 'wgStyleDirectory' => 'notTestingwgStyleDirectory',
+ 'wgStylePath' => 'notTestingwgStylePath'
+ );
+
+ $request = $this->getMockBuilder('\WebRequest')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new SetupAfterCache(
+ $bootstrapManager,
+ $configuration,
+ $request
+ );
+
+ $instance->process();
+ }
+
+ /**
+ * @covers ::process
+ * @covers ::registerExternalLessVariables
+ *
+ * @dataProvider processWithRequestedLayoutFileProvider
+ */
+ public function testProcessWithRequestedLayoutFile( $availableLayoutFiles, $defaultLayoutFile, $requestedLayout, $expectedLayoutfile ) {
+
+ $bootstrapManager = $this->getMockBuilder( '\Bootstrap\BootstrapManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $configuration = array(
+ 'egChameleonAvailableLayoutFiles' => $availableLayoutFiles,
+ 'egChameleonLayoutFile' => $defaultLayoutFile,
+ 'IP' => 'notTestingIP',
+ 'wgScriptPath' => 'notTestingwgScriptPath',
+ 'wgStyleDirectory' => 'notTestingwgStyleDirectory',
+ 'wgStylePath' => 'notTestingwgStylePath'
+ );
+
+ $request = $this->getMockBuilder('\WebRequest')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $request->expects( $this->once() )
+ ->method( 'getVal' )
+ ->will( $this->returnValue( $requestedLayout ) );
+
+ $instance = new SetupAfterCache(
+ $bootstrapManager,
+ $configuration,
+ $request
+ );
+
+ $instance->process();
+
+ $this->assertEquals(
+ $expectedLayoutfile,
+ $configuration['egChameleonLayoutFile']
+ );
+ }
+
+ public function processWithRequestedLayoutFileProvider() {
+
+ $provider = array();
+
+ // no layout files available => keep default layout file
+ $provider[] = array(
+ null,
+ 'standard.xml',
+ 'someOtherLayout',
+ 'standard.xml'
+ );
+
+ // no specific layout requested => keep default layout file
+ $provider[] = array(
+ array(
+ 'layout1' => 'layout1.xml',
+ 'layout2' => 'layout2.xml',
+ ),
+ 'standard.xml',
+ null,
+ 'standard.xml'
+ );
+
+ // requested layout not available => keep default layout file
+ $provider[] = array(
+ array(
+ 'layout1' => 'layout1.xml',
+ 'layout2' => 'layout2.xml',
+ ),
+ 'standard.xml',
+ 'someOtherLayout',
+ 'standard.xml'
+ );
+
+ // requested layout available => return requested layout file
+ $provider[] = array(
+ array(
+ 'layout1' => 'layout1.xml',
+ 'layout2' => 'layout2.xml',
+ ),
+ 'standard.xml',
+ 'layout1',
+ 'layout1.xml'
+ );
+
+ return $provider;
+ }
+
+ /**
+ * @covers ::adjustConfiguration
+ *
+ * @dataProvider adjustConfigurationProvider
+ */
+ public function testAdjustConfiguration( $origConfig, $changes, $expected ) {
+
+ $bootstrapManager = $this->getMockBuilder( '\Bootstrap\BootstrapManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $request = $this->getMockBuilder('\WebRequest')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new SetupAfterCache(
+ $bootstrapManager,
+ $changes,
+ $request
+ );
+
+ $instance->adjustConfiguration( $origConfig );
+
+ $this->assertEquals( $expected, $origConfig );
+ }
+
+ /**
+ * @covers ::process
+ * @covers ::addLateSettings
+ *
+ * @depends testAdjustConfiguration
+ *
+ * @dataProvider lateSettingsProvider
+ */
+ public function testProcessWithLateSettingsToAdjustConfiguration( $configuration, $expected ) {
+
+ $bootstrapManager = $this->getMockBuilder( '\Bootstrap\BootstrapManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dir = $this->getWorkDirectory();
+ $IP = dirname(dirname($dir));
+
+ $defaultConfiguration = array(
+ 'IP' => $IP,
+ 'wgScriptPath' => 'notTestingwgScriptPath',
+ 'wgStylePath' => 'notTestingwgStylePath',
+ 'wgStyleDirectory' => 'notTestingwgStyleDirectory',
+ 'wgResourceModules' => array(),
+ );
+
+ $expected[ 'chameleonLocalPath' ] = $defaultConfiguration[ 'wgStyleDirectory' ] . '/chameleon';
+ $expected[ 'chameleonRemotePath' ] = $defaultConfiguration[ 'wgStylePath' ] . '/chameleon';
+
+ $expected[ 'wgResourceModules' ] = array();
+ $expected[ 'wgResourceModules' ][ 'skin.chameleon.jquery-sticky' ] = array(
+ 'localBasePath' => $expected[ 'chameleonLocalPath' ] . '/resources/js',
+ 'remoteBasePath' => $expected[ 'chameleonRemotePath' ] . '/resources/js',
+ 'group' => 'skin.chameleon',
+ 'skinScripts' => array(
+ 'chameleon' => array( 'sticky-kit/jquery.sticky-kit.js', 'Components/Modifications/sticky.js' )
+ )
+ );
+
+ $configurationToBeAdjusted = $configuration + $defaultConfiguration;
+
+ $request = $this->getMockBuilder('\WebRequest')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new SetupAfterCache(
+ $bootstrapManager,
+ $configurationToBeAdjusted,
+ $request
+ );
+
+ $instance->process();
+
+ $this->assertEquals(
+ $expected + $defaultConfiguration,
+ $configurationToBeAdjusted
+ );
+ }
+
+ /**
+ * Provides test data for the lateSettings test
+ */
+ public function lateSettingsProvider() {
+
+ $provider = array();
+
+ $provider[ ] = array(
+ array(),
+ array()
+ );
+
+ $provider[ ] = array(
+ array(
+ 'wgVisualEditorSupportedSkins' => array(),
+ ),
+ array(
+ 'wgVisualEditorSupportedSkins' => array(),
+ )
+ );
+
+ $provider[ ] = array(
+ array(
+ 'egChameleonEnableVisualEditor' => true,
+ ),
+ array(
+ 'egChameleonEnableVisualEditor' => true,
+ )
+ );
+
+ $provider[ ] = array(
+ array(
+ 'egChameleonEnableVisualEditor' => true,
+ 'wgVisualEditorSupportedSkins' => array( 'foo' ),
+ ),
+ array(
+ 'egChameleonEnableVisualEditor' => true,
+ 'wgVisualEditorSupportedSkins' => array( 'foo', 'chameleon' ),
+ )
+ );
+
+ $provider[ ] = array(
+ array(
+ 'egChameleonEnableVisualEditor' => true,
+ 'wgVisualEditorSupportedSkins' => array( 'foo', 'chameleon' ),
+ ),
+ array(
+ 'egChameleonEnableVisualEditor' => true,
+ 'wgVisualEditorSupportedSkins' => array( 'foo', 'chameleon' ),
+ )
+ );
+
+ $provider[ ] = array(
+ array(
+ 'egChameleonEnableVisualEditor' => false,
+ 'wgVisualEditorSupportedSkins' => array( 'chameleon', 'foo' => 'chameleon', 'foo' ),
+ ),
+ array(
+ 'egChameleonEnableVisualEditor' => false,
+ 'wgVisualEditorSupportedSkins' => array( 1 => 'foo' ),
+ )
+ );
+
+ return $provider;
+ }
+
+ /**
+ * Provides test data for the adjustConfiguration test
+ */
+ public function adjustConfigurationProvider() {
+
+ $provider = array();
+
+ $provider[ ] = array(
+ array(
+ 'key1' => 'value1',
+ 'key2' => 'value2',
+ ),
+ array(
+ 'key2' => 'value2changed',
+ 'key3' => 'value3changed',
+ ),
+ array(
+ 'key1' => 'value1',
+ 'key2' => 'value2changed',
+ 'key3' => 'value3changed',
+ )
+ );
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Unit/Menu/MenuFromLinesTest.php b/www/wiki/skins/chameleon/tests/phpunit/Unit/Menu/MenuFromLinesTest.php
new file mode 100644
index 00000000..cd8cbcc5
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Unit/Menu/MenuFromLinesTest.php
@@ -0,0 +1,127 @@
+<?php
+/**
+ * File containing the MenuFromLinesTest class
+ *
+ * @copyright (C) 2013 - 2015, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Unit\Menu;
+use Skins\Chameleon\Menu\MenuFromLines;
+
+/**
+ * Class MenuFromLinesTest
+ *
+ * @coversDefaultClass \Skins\Chameleon\Menu\MenuFromLines
+ * @covers ::<private>
+ * @covers ::<protected>
+ *
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.1.2
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class MenuFromLinesTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @covers ::__construct
+ */
+ public function testCanConstruct() {
+
+ $lines = array();
+
+ /** @var MenuFromLines $instance */
+ $instance = new MenuFromLines( $lines, true );
+
+ $this->assertInstanceOf(
+ 'Skins\Chameleon\Menu\MenuFromLines',
+ $instance
+ );
+ }
+
+ /**
+ * @covers ::__construct
+ *
+ * Just checking that giving an item data parameter does not immediately
+ * break the constructor. No actual functionality beyond that is tested.
+ */
+ public function testCanConstructWithItemData() {
+
+ $lines = array();
+
+ /** @var MenuFromLines $instance */
+ $instance = new MenuFromLines( $lines, true, array(
+ 'text' => 'foo',
+ 'href' => 'bar',
+ 'depth' => 42
+ ) );
+
+ $this->assertInstanceOf(
+ 'Skins\Chameleon\Menu\MenuFromLines',
+ $instance
+ );
+ }
+
+ /**
+ * @covers ::getHtml
+ * @covers ::parseLines
+ */
+ public function testBuildEmptyMenu() {
+
+ $lines = array(
+ '',
+ '* Foo',
+ '** | FooBar',
+ '*** http://foo.com | FooBarBaz',
+ '*** # | FooBarQuok',
+ '* Test | Bar',
+ );
+
+ $ap = $GLOBALS[ 'wgArticlePath' ];
+
+ $expected =
+ "\t<ul>\n" .
+ "\t\t<li>\n" .
+ "\t\t\t<a href=\"" . str_replace( '$1', 'Foo', $ap ) . "\">Foo</a>\n" .
+ "\t\t\t<ul>\n" .
+ "\t\t\t\t<li>\n" .
+ "\t\t\t\t\t<a href=\"#" . "\">FooBar</a>\n" .
+ "\t\t\t\t\t<ul>\n" .
+ "\t\t\t\t\t\t<li><a href=\"http://foo.com\">FooBarBaz</a></li>\n" .
+ "\t\t\t\t\t\t<li><a href=\"#\">FooBarQuok</a></li>\n" .
+ "\t\t\t\t\t</ul>\n" .
+ "\t\t\t\t</li>\n" .
+ "\t\t\t</ul>\n" .
+ "\t\t</li>\n" .
+ "\t\t<li><a href=\"" . str_replace( '$1', 'Test', $ap ) . "\">Bar</a></li>\n" .
+ "\t</ul>\n";
+
+ /** @var MenuFromLines $instance */
+ $instance = new MenuFromLines( $lines, true );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getHtml()
+ );
+
+ }
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Util/ColoringTextUIResultPrinter.php b/www/wiki/skins/chameleon/tests/phpunit/Util/ColoringTextUIResultPrinter.php
new file mode 100644
index 00000000..6d55b1b0
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Util/ColoringTextUIResultPrinter.php
@@ -0,0 +1,105 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Util;
+
+/**
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class ColoringTextUIResultPrinter extends \PHPUnit_TextUI_ResultPrinter {
+
+ /**
+ * @var array
+ */
+ protected static $ansiCodes = array(
+ 'bold' => 1,
+ 'fg-black' => 30,
+ 'fg-red' => 31,
+ 'fg-green' => 32,
+ 'fg-yellow' => 33,
+ 'fg-cyan' => 36,
+ 'fg-white' => 37,
+ 'bg-red' => 41,
+ 'bg-green' => 42,
+ 'bg-yellow' => 43
+ );
+
+ public function endTest(\PHPUnit_Framework_Test $test, $time)
+ {
+ if (!$this->lastTestFailed) {
+
+ $color = '';
+ if ( method_exists($test, 'getSuccessColor' )) {
+ $color = $test->getSuccessColor();
+ }
+ $this->writeProgressWithColor($color, '.');
+
+ }
+
+ if ($test instanceof \PHPUnit_Framework_TestCase) {
+ $this->numAssertions += $test->getNumAssertions();
+ } elseif ($test instanceof \PHPUnit_Extensions_PhptTestCase) {
+ $this->numAssertions++;
+ }
+
+ $this->lastTestFailed = false;
+
+ if ($test instanceof \PHPUnit_Framework_TestCase) {
+ if (!$test->hasPerformedExpectationsOnOutput()) {
+ $this->write($test->getActualOutput());
+ }
+ }
+ }
+
+ protected function formatWithColor($color, $buffer)
+ {
+ if (!$this->colors) {
+ return $buffer;
+ }
+
+ $codes = array_filter( array_map('trim', explode(',', $color)) );
+ $lines = explode("\n", $buffer);
+ $padding = max(array_map('strlen', $lines));
+
+ $styles = array();
+ foreach ($codes as $code) {
+ $styles[] = self::$ansiCodes[$code];
+ }
+ $style = sprintf("\x1b[%sm", implode(';', $styles));
+
+ $styledLines = array();
+ foreach ($lines as $line) {
+ $styledLines[] = $style . str_pad($line, $padding) . "\x1b[0m";
+ }
+
+ return implode("\n", $styledLines);
+ }
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Util/DocumentElementFinder.php b/www/wiki/skins/chameleon/tests/phpunit/Util/DocumentElementFinder.php
new file mode 100644
index 00000000..6f0d0ac5
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Util/DocumentElementFinder.php
@@ -0,0 +1,124 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke, mwjames
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Util;
+
+use DOMDocument;
+use DOMElement;
+
+use RuntimeException;
+
+/**
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author mwjames
+ * @author Stephan Gambke
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class DocumentElementFinder {
+
+ protected $file = null;
+ protected $document = null;
+
+ /**
+ * @since 1.0
+ *
+ * @param string $file
+ */
+ public function __construct( $file ) {
+ $this->file = $file;
+ }
+
+ /**
+ * @since 1.0
+ *
+ * @param string $type
+ *
+ * @return DOMElement|null
+ */
+ public function getComponentByTypeAttribute( $type ) {
+
+ $elements = $this->getComponentsByTypeAttribute( $type );
+
+ if ( count( $elements ) > 0 ) {
+ return array_shift( $elements );
+ }
+
+ return null;
+ }
+
+ /**
+ * @since 1.0
+ *
+ * @param string $type
+ *
+ * @return DOMElement[]
+ */
+ public function getComponentsByTypeAttribute( $type ) {
+
+ $elements = array();
+
+ $elementList = $this->getDocument()->getElementsByTagName( strtolower( $type ) );
+ foreach( $elementList as $element ){
+ $elements[] = $element;
+ }
+
+ $elementList = $this->getDocument()->getElementsByTagName( '*' );
+ foreach ( $elementList as $element ) {
+ if ( $element instanceOf DOMElement && $element->hasAttribute( 'type' ) && $element->getAttribute( 'type' ) === $type ) {
+ $elements[] = $element;
+ }
+ }
+
+ return $elements;
+ }
+
+ protected function getDocument() {
+
+ if ( $this->document !== null ) {
+ return $this->document;
+ }
+
+ $file = str_replace( array( '\\', '/' ), DIRECTORY_SEPARATOR, $this->file );
+
+ if ( !is_readable( $file ) ) {
+ throw new RuntimeException( "Expected an accessible {$file} path" );
+ }
+
+ $document = new DOMDocument;
+ $document->validateOnParse = true;
+
+ if ( !$document->load( $file ) ) {
+ throw new RuntimeException( "Unable to load {$file} file" );
+ }
+
+ $document->normalizeDocument();
+
+ return $document;
+ }
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Util/MockupFactory.php b/www/wiki/skins/chameleon/tests/phpunit/Util/MockupFactory.php
new file mode 100644
index 00000000..dee59e0f
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Util/MockupFactory.php
@@ -0,0 +1,335 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2015, Stephan Gambke
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Util;
+
+/**
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author Stephan Gambke
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class MockupFactory {
+
+ private $testCase;
+ private $configuration = array(
+ 'UserIsLoggedIn' => false,
+ 'UserNewMessageLinks' => array(),
+ 'UserEffectiveGroups' => array( '*' ),
+ 'UserRights' => array(),
+ );
+
+ public function __construct( \PHPUnit_Framework_TestCase $testCase ) {
+ $this->testCase = $testCase;
+ }
+
+ /**
+ * Returns a new factory. Convenience method to avoid having to use the constructor.
+ *
+ * @param \PHPUnit_Framework_TestCase $testCase
+ *
+ * @return MockupFactory
+ */
+ public static function makeFactory( \PHPUnit_Framework_TestCase $testCase ) {
+ return new self( $testCase );
+ }
+
+ public function set( $key, $value ) {
+ $this->configuration[ $key ] = $value;
+ }
+
+ public function getChameleonSkinTemplateStub() {
+
+ $chameleonTemplate = $this->testCase->getMockBuilder( '\Skins\Chameleon\ChameleonTemplate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $chameleonTemplate->data = $this->getSkinTemplateDummyDataSetForMainNamespace();
+ $chameleonTemplate->translator = $this->getTranslatorStub();
+
+ $dataMap = array_map(
+ function ( $key, $value ) {
+ return array( $key, null, $value );
+ },
+ array_keys( $chameleonTemplate->data ),
+ array_values( $chameleonTemplate->data )
+ );
+
+ $chameleonTemplate->expects( $this->testCase->any() )
+ ->method( 'get' )
+ ->will( $this->testCase->returnValueMap( $dataMap ) );
+
+ $chameleonTemplate->expects( $this->testCase->any() )
+ ->method( 'getMsg' )
+ ->will( $this->testCase->returnValue( $this->getMessageStub() ) );
+
+ $chameleonTemplate->expects( $this->testCase->any() )
+ ->method( 'getSkin' )
+ ->will( $this->testCase->returnValue( $this->getSkinStub() ) );
+
+ $chameleonTemplate->expects( $this->testCase->any() )
+ ->method( 'getComponent' )
+ ->will( $this->testCase->returnValue( $this->getComponentStub() ) );
+
+ $chameleonTemplate->expects( $this->testCase->any() )
+ ->method( 'getSidebar' )
+ ->will( $this->testCase->returnValue( array() ) );
+
+ $chameleonTemplate->expects( $this->testCase->any() )
+ ->method( 'getToolbox' )
+ ->will( $this->testCase->returnValue( array() ) );
+
+ $chameleonTemplate->expects( $this->testCase->any() )
+ ->method( 'getPersonalTools' )
+ ->will( $this->testCase->returnValue( array( 'foo' => array(), 'bar' => array() ) ) );
+
+ $chameleonTemplate->expects( $this->testCase->any( 0 ) )
+ ->method( 'getFooterLinks' )
+ ->will( $this->testCase->returnValue(
+ array(
+ 'category1' => array( 'key1', 'key2' ),
+ 'category2' => array( 'key3', 'key4' ),
+ 'places' => array( 'privacy', 'about', 'disclaimer' ),
+ )
+ )
+ );
+
+ return $chameleonTemplate;
+ }
+
+ /**
+ * Dummy values are by no means to represent a particular intention or
+ * objective and merely used to pass through the respective method
+ *
+ * Testing specific conditions should be done separately in each sub
+ * component
+ */
+ protected function getSkinTemplateDummyDataSetForMainNamespace() {
+ return array(
+
+ // Required by Logo
+ 'logopath' => 'foo',
+ 'sitename' => 'bar',
+
+ // Required by NavMenu
+ 'nav_urls' => array(
+ 'mainpage' => array( 'href' => 'bat' )
+ ),
+
+ // Required by PageTools
+ 'content_navigation' => array(
+ 'namespaces' =>
+ array(
+ 'talk' =>
+ array(
+ 'class' => '',
+ 'text' => 'Discussion',
+ 'href' => '/mw/index.php?title=Talk:Main_Page',
+ 'primary' => true,
+ 'context' => 'talk',
+ 'id' => 'ca-talk',
+ ),
+ ),
+ 'views' =>
+ array(
+ 'view' =>
+ array(
+ 'class' => 'selected',
+ 'text' => 'View',
+ 'href' => '/mw/index.php/Main_Page',
+ 'primary' => true,
+ 'redundant' => true,
+ 'id' => 'ca-view',
+ ),
+ 'edit' =>
+ array(
+ 'class' => '',
+ 'text' => 'Edit',
+ 'href' => '/mw/index.php?title=Main_Page&action=edit',
+ 'primary' => true,
+ 'id' => 'ca-edit',
+ ),
+ 'history' =>
+ array(
+ 'class' => false,
+ 'text' => 'History',
+ 'href' => '/mw/index.php?title=Main_Page&action=history',
+ 'rel' => 'archives',
+ 'id' => 'ca-history',
+ ),
+ ),
+ ),
+
+ // Required by SearchBar
+ 'wgScript' => 'bam',
+ 'searchtitle' => 'jouy',
+
+ // Required by MainContent
+ 'subtitle' => 'SomeSubtitle',
+ 'undelete' => 'SomeUndeleteMessage',
+ 'dataAfterContent' => 'SomeDataAfterContent',
+ );
+ }
+
+ protected function getTranslatorStub() {
+
+ $translator = $this->testCase->getMockBuilder( '\stdClass' )
+ ->setMethods( array( 'translate' ) )
+ ->getMock();
+
+ $translator->expects( $this->testCase->any() )
+ ->method( 'translate' )
+ ->will( $this->testCase->returnValue( 'translate' ) );
+
+ return $translator;
+ }
+
+ protected function getMessageStub() {
+
+ $message = $this->testCase->getMockBuilder( '\Message' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $message->expects( $this->testCase->any() )
+ ->method( 'params' )
+ ->will( $this->testCase->returnSelf() );
+
+ return $message;
+
+ }
+
+ protected function getSkinStub() {
+
+ $title = \Title::newFromText( 'FOO' );
+ $request = new \FauxRequest();
+
+ $skin = $this->testCase->getMockBuilder( '\SkinChameleon' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skin->expects( $this->testCase->any() )
+ ->method( 'getTitle' )
+ ->will( $this->testCase->returnValue( $title ) );
+
+ $skin->expects( $this->testCase->any() )
+ ->method( 'getUser' )
+ ->will( $this->testCase->returnValue( $this->getUserStub() ) );
+
+ $skin->expects( $this->testCase->any() )
+ ->method( 'getRequest' )
+ ->will( $this->testCase->returnValue( $request ) );
+
+ $skin->expects( $this->testCase->any() )
+ ->method( 'getComponentFactory' )
+ ->will( $this->testCase->returnValue( $this->getComponentFactoryStub() ) );
+
+ return $skin;
+ }
+
+ protected function getComponentStub() {
+
+ $component = $this->testCase->getMockBuilder( 'Skins\Chameleon\Components\Component' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $component->expects( $this->testCase->any() )
+ ->method( 'getHtml' )
+ ->will( $this->testCase->returnValue( 'SomePlainText' ) );
+
+ return $component;
+ }
+
+ protected function getUserStub() {
+
+ $user = $this->testCase->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $user->expects( $this->testCase->any() )
+ ->method( 'isLoggedIn' )
+ ->will( $this->testCase->returnValue( $this->get( 'UserIsLoggedIn', true ) ) );
+
+ $user->expects( $this->testCase->any() )
+ ->method( 'getNewMessageLinks' )
+ ->will( $this->testCase->returnValue( $this->get( 'UserNewMessageLinks', 0 ) ) );
+
+ $user->expects( $this->testCase->any() )
+ ->method( 'getEffectiveGroups' )
+ ->will( $this->testCase->returnValue( $this->get( 'UserEffectiveGroups', 0 ) ) );
+
+ $user->expects( $this->testCase->any() )
+ ->method( 'getTalkPage' )
+ ->will( $this->testCase->returnValue( $this->getTitleStub() ) );
+
+ $user->expects( $this->testCase->any() )
+ ->method( 'getRights' )
+ ->will( $this->testCase->returnValue( $this->get( 'UserRights', array() ) ) );
+
+ return $user;
+
+ }
+
+ public function get( $key, $default = null ) {
+
+ if ( isset( $this->configuration[ $key ] ) ) {
+ return $this->configuration[ $key ];
+ } else {
+ return $default;
+ }
+
+ }
+
+ protected function getTitleStub() {
+
+ $title = $this->testCase->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->testCase->any() )
+ ->method( 'getLinkUrl' )
+ ->will( $this->testCase->returnValue( 'SomeLinkUrl' ) );
+
+ return $title;
+
+ }
+
+ protected function getComponentFactoryStub() {
+
+ $factory = $this->testCase->getMockBuilder( 'Skins\Chameleon\ComponentFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $factory->expects( $this->testCase->any() )
+ ->method( 'getComponent' )
+ ->will( $this->testCase->returnValue( $this->getComponentStub() ) );
+
+
+ return $factory;
+
+ }
+
+}
diff --git a/www/wiki/skins/chameleon/tests/phpunit/Util/XmlFileProvider.php b/www/wiki/skins/chameleon/tests/phpunit/Util/XmlFileProvider.php
new file mode 100644
index 00000000..78b04c54
--- /dev/null
+++ b/www/wiki/skins/chameleon/tests/phpunit/Util/XmlFileProvider.php
@@ -0,0 +1,85 @@
+<?php
+/**
+ * This file is part of the MediaWiki skin Chameleon.
+ *
+ * @copyright 2013 - 2014, Stephan Gambke, mwjames
+ * @license GNU General Public License, version 3 (or any later version)
+ *
+ * The Chameleon skin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * The Chameleon skin 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup Skins
+ */
+
+namespace Skins\Chameleon\Tests\Util;
+
+use RuntimeException;
+
+/**
+ * @group skins-chameleon
+ * @group mediawiki-databaseless
+ *
+ * @author mwjames
+ * @since 1.0
+ * @ingroup Skins
+ * @ingroup Test
+ */
+class XmlFileProvider {
+
+ protected $path = null;
+
+ /**
+ * @since 1.0
+ *
+ * @param string $path
+ */
+ public function __construct( $path ) {
+ $this->path = $path;
+ }
+
+ /**
+ * @since 1.0
+ *
+ * @return array
+ */
+ public function getFiles() {
+ return $this->loadXmlFiles( $this->readDirectory( $this->path ) );
+ }
+
+ protected function readDirectory( $path ) {
+
+ $path = str_replace( array( '\\', '/' ), DIRECTORY_SEPARATOR, $path );
+
+ if ( is_readable( $path ) ) {
+ return $path;
+ }
+
+ throw new RuntimeException( "Expected an accessible {$path} path" );
+ }
+
+ protected function loadXmlFiles( $path ) {
+
+ $files = array();
+ $directoryIterator = new \RecursiveDirectoryIterator( $path );
+
+ foreach ( new \RecursiveIteratorIterator( $directoryIterator ) as $fileInfo ) {
+ if ( strtolower( substr( $fileInfo->getFilename(), -4 ) ) === '.xml' ) {
+ $files[] = $fileInfo->getPathname();
+ }
+ }
+
+ return $files;
+ }
+
+}