From: Tim Starling Date: Fri, 25 Jun 2010 05:55:23 +0000 (+0000) Subject: * Integrated the selenium tests into MediaWiki properly, and removed the insecure... X-Git-Tag: 1.31.0-rc.0~36393 X-Git-Url: https://git.cyclocoop.org/%7B%24www_url%7Dadmin/compta/banques/%7B%7B%20url_for%28%27admin_users%27%29%20%7D%7D?a=commitdiff_plain;h=1fcfd134d15d17c89894094b5dc38f29f83e95e9;p=lhc%2Fweb%2Fwiklou.git * Integrated the selenium tests into MediaWiki properly, and removed the insecure LocalSeleniumSettings.php concept. * Removed the insecure web entry point hiding in the maintenance directory, in RunSeleniumTests.php. Replaced it with a special page interface, with CSRF protection and access control. If you wanted a secure web entry point, then I suppose this is how it would be done, but I think it should be killed ASAP. * As in r68544, removed as many require() calls as possible, since nobody seems to know how to do them properly. Made the usual changes to make classes autoloader-compatible: class constants instead of define(), no file-scope registration code. --- diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index 186dc21b58..b4ae511b80 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -593,6 +593,7 @@ $wgAutoloadLocalClasses = array( 'SpecialRecentChanges' => 'includes/specials/SpecialRecentchanges.php', 'SpecialRecentchangeslinked' => 'includes/specials/SpecialRecentchangeslinked.php', 'SpecialSearch' => 'includes/specials/SpecialSearch.php', + 'SpecialSelenium' => 'includes/specials/SpecialSelenium.php', 'SpecialStatistics' => 'includes/specials/SpecialStatistics.php', 'SpecialTags' => 'includes/specials/SpecialTags.php', 'SpecialUnlockdb' => 'includes/specials/SpecialUnlockdb.php', @@ -638,25 +639,40 @@ $wgAutoloadLocalClasses = array( # maintenance 'AnsiTermColorer' => 'maintenance/parserTests.inc', - 'ApiTestSetup' => 'maintenance/tests/ApiSetup.php', 'DbTestPreviewer' => 'maintenance/parserTests.inc', 'DbTestRecorder' => 'maintenance/parserTests.inc', 'DeleteArchivedFilesImplementation' => 'maintenance/deleteArchivedFiles.inc', 'DeleteArchivedRevisionsImplementation' => 'maintenance/deleteArchivedRevisions.inc', 'DummyTermColorer' => 'maintenance/parserTests.inc', - 'MediaWikiTestSetup' => 'maintenance/tests/MediaWiki_Setup.php', - 'PHPUnitTestRecorder' => 'maintenance/tests/ParserHelpers.php', 'ParserTest' => 'maintenance/parserTests.inc', 'ParserTestParserHook' => 'maintenance/parserTestsParserHook.php', 'ParserTestStaticParserHook' => 'maintenance/parserTestsStaticParserHook.php', - 'ParserTestSuiteBackend' => 'maintenance/tests/ParserHelpers.php', - 'ParserUnitTest' => 'maintenance/tests/ParserHelpers.php', 'RemoteTestRecorder' => 'maintenance/parserTests.inc', - 'SearchEngineTest' => 'maintenance/tests/SearchEngineTest.php', 'SevenZipStream' => 'maintenance/7zip.inc', 'TestFileIterator' => 'maintenance/parserTests.inc', 'TestRecorder' => 'maintenance/parserTests.inc', + + # maintenance/tests + 'ApiTestSetup' => 'maintenance/tests/ApiSetup.php', + 'MediaWikiTestSetup' => 'maintenance/tests/MediaWiki_Setup.php', + 'PHPUnitTestRecorder' => 'maintenance/tests/ParserHelpers.php', + 'ParserTestSuiteBackend' => 'maintenance/tests/ParserHelpers.php', + 'ParserUnitTest' => 'maintenance/tests/ParserHelpers.php', + 'SearchEngineTest' => 'maintenance/tests/SearchEngineTest.php', 'UploadFromUrlTest' => 'maintenance/tests/UploadFromUrlTest.php', + + # maintenance/tests/selenium + 'SimpleSeleniumTest' => 'maintenance/tests/selenium/SimpleSeleniumTest.php', + 'Selenium' => 'maintenance/tests/selenium/Selenium.php', + 'SeleniumLoader' => 'maintenance/tests/selenium/SeleniumLoader.php', + 'SeleniumTestCase' => 'maintenance/tests/selenium/SeleniumTestCase.php', + 'SeleniumTestConsoleLogger' => 'maintenance/tests/selenium/SeleniumTestConsoleLogger.php', + 'SeleniumTestHTMLLogger' => 'maintenance/tests/selenium/SeleniumTestHTMLLogger.php', + 'SeleniumTestListener' => 'maintenance/tests/selenium/SeleniumTestListener.php', + 'SeleniumTestSuite' => 'maintenance/tests/selenium/SeleniumTestSuite.php', + 'SimpleSeleniumTest' => 'maintenance/tests/selenium/SimpleSeleniumTest.php', + + # maintenance/language 'csvStatsOutput' => 'maintenance/language/StatOutputs.php', 'statsOutput' => 'maintenance/language/StatOutputs.php', 'textStatsOutput' => 'maintenance/language/StatOutputs.php', diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index b6e980c8f3..f2c3b3366d 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -3701,6 +3701,50 @@ $wgParserTestFiles = array( */ $wgParserTestRemote = false; +/** + * Enable Selenium test framework. + * This enables maintenance/tests/RunSeleniumTests.php and [[Special:Selenium]]. + */ +$wgEnableSelenium = false; + +/** List of Selenium test classes. These must be registered with the autoloader. */ +$wgSeleniumTests = array( + 'SimpleSeleniumTest' +); + + +/** Hostname of selenium server */ +$wgSeleniumTestsSeleniumHost = 'localhost'; + +/** URL of the wiki to be tested. By default, the local wiki is used. */ +$wgSeleniumTestsWikiUrl = false; + +/** Port used by selenium server. */ +$wgSeleniumServerPort = 4444; + +/** Wiki login username. Used by Selenium to log onto the wiki. */ +$wgSeleniumTestsWikiUser = 'Wikiuser'; + +/** Wiki login password. Used by Selenium to log onto the wiki. */ +$wgSeleniumTestsWikiPassword = ''; + +/** + * Common browsers on Windows platform. Modify for other platforms or + * other Windows browsers. + * Use the *chrome handler in order to be able to test file uploads. + * Further solution suggestions: http://www.brokenbuild.com/blog/2007/06/07/testing-file-uploads-with-selenium-rc-and-firefoxor-reducing-javascript-security-in-firefox-for-fun-and-profit/ + */ +$wgSeleniumTestsBrowsers = array( + 'firefox' => '*firefox /usr/bin/firefox', + 'iexplorer' => '*iexploreproxy', + 'opera' => '*chrome /usr/bin/opera', +); + +/** Actually, use this browser */ +$wgSeleniumTestsUseBrowser = 'firefox'; + + + /** @} */ # end of profiling, testing and debugging } /************************************************************************//** diff --git a/includes/SpecialPage.php b/includes/SpecialPage.php index 1cfbc18abc..1987303182 100644 --- a/includes/SpecialPage.php +++ b/includes/SpecialPage.php @@ -207,6 +207,7 @@ class SpecialPage { static function initList() { global $wgSpecialPages; global $wgDisableCounters, $wgDisableInternalSearch, $wgEmailAuthentication; + global $wgEnableSelenium; if ( self::$mListInitialised ) { return; @@ -229,6 +230,10 @@ class SpecialPage { self::$mList['Invalidateemail'] = 'EmailInvalidation'; } + if ( $wgEnableSelenium ) { + self::$mList['Selenium'] = 'SpecialSelenium'; + } + # Add extension special pages self::$mList = array_merge( self::$mList, $wgSpecialPages ); diff --git a/includes/User.php b/includes/User.php index aa48403fad..ddb36bf11c 100644 --- a/includes/User.php +++ b/includes/User.php @@ -167,6 +167,7 @@ class User { 'reupload', 'reupload-shared', 'rollback', + 'selenium', 'sendemail', 'siteadmin', 'suppressionlog', diff --git a/includes/specials/SpecialSelenium.php b/includes/specials/SpecialSelenium.php new file mode 100644 index 0000000000..442c2806c0 --- /dev/null +++ b/includes/specials/SpecialSelenium.php @@ -0,0 +1,62 @@ +setHeaders(); + if ( !$this->userCanExecute( $wgUser ) ) { + $this->displayRestrictionError(); + return; + } + + if ( $wgRequest->wasPosted() && $wgUser->matchEditToken( $wgRequest->getVal( 'token' ) ) ) { + $this->runTests(); + } + $wgOut->addHTML( + Html::openElement( 'form', array( + 'method' => 'POST', + 'action' => $this->getTitle()->getLocalUrl(), + ) ) . + Html::input( 'submit', 'Run tests', 'submit' ) . + Html::hidden( 'token', $wgUser->editToken() ) . + '' + ); + } + + function runTests() { + global $wgSeleniumTests, $wgOut; + SeleniumLoader::load(); + + $result = new PHPUnit_Framework_TestResult; + $logger = new SeleniumTestHTMLLogger; + $result->addListener( new SeleniumTestListener( $logger ) ); + + // run tests + $suite = new SeleniumTestSuite; + foreach ( $wgSeleniumTests as $testClass ) { + $suite->addTest( new $testClass ); + } + $wgOut->addHTML( '
' ); + $suite->run( $result ); + $wgOut->addHTML( '
' ); + } +} + diff --git a/languages/messages/MessagesEn.php b/languages/messages/MessagesEn.php index af808250c4..2d58aee8c8 100644 --- a/languages/messages/MessagesEn.php +++ b/languages/messages/MessagesEn.php @@ -1936,6 +1936,7 @@ You can also choose to let others contact you through your user or talk page wit 'right-override-export-depth' => 'Export pages including linked pages up to a depth of 5', 'right-sendemail' => 'Send e-mail to other users', 'right-revisionmove' => 'Move revisions', +'right-selenium' => 'Run Selenium tests', # User rights log 'rightslog' => 'User rights log', diff --git a/maintenance/tests/RunSeleniumTests.php b/maintenance/tests/RunSeleniumTests.php index d7751c5548..f70f279f9e 100644 --- a/maintenance/tests/RunSeleniumTests.php +++ b/maintenance/tests/RunSeleniumTests.php @@ -22,79 +22,33 @@ * http://www.gnu.org/copyleft/gpl.html */ -define( 'MEDIAWIKI', true ); define( 'SELENIUMTEST', true ); -// Here, you can override standard setting -if ( file_exists( 'selenium/LocalSeleniumSettings.php' ) ) { - include_once 'selenium/LocalSeleniumSettings.php'; -} else { - echo "You must provide local settings in LocalSeleniumSettings.php\n"; - die( -1 ); -} - -// Command line only -if ( $wgSeleniumTestsRunMode == 'cli' && php_sapi_name() != 'cli' ) { - echo "Must be run from the command line.\n"; - die( -1 ); -} - -// Get command line parameters -if ( $wgSeleniumTestsRunMode == 'cli' ) { - require_once( dirname( __FILE__ ) . '/../commandLine.inc' ); - if ( isset( $options['help'] ) ) { - echo << Port used by selenium server to accept commands - --help Show this help message +--port= Port used by selenium server to accept commands +--help Show this help message ENDS; - exit( 0 ); - } - - if ( isset( $options['port'] ) ) { - $wgSeleniumServerPort = (int) $options['port']; - } + exit( 1 ); } -// requires PHPUnit 3.4 -require_once 'Testing/Selenium.php'; -require_once 'PHPUnit/Framework.php'; -require_once 'PHPUnit/Extensions/SeleniumTestCase.php'; +if ( isset( $options['port'] ) ) { + $wgSeleniumServerPort = (int) $options['port']; +} -// include seleniumTestsuite -require_once 'selenium/SeleniumTestHTMLLogger.php'; -require_once 'selenium/SeleniumTestConsoleLogger.php'; -require_once 'selenium/SeleniumTestListener.php'; -require_once 'selenium/Selenium.php'; -require_once 'selenium/SeleniumTestSuite.php'; -require_once 'selenium/SeleniumTestCase.php'; +SeleniumLoader::load(); $result = new PHPUnit_Framework_TestResult; -switch ( $wgSeleniumTestsRunMode ) { - case 'html': - $logger = new SeleniumTestHTMLLogger; - break; - case 'cli': - $logger = new SeleniumTestConsoleLogger; - break; -} - +$logger = new SeleniumTestConsoleLogger; $result->addListener( new SeleniumTestListener( $logger ) ); -$wgSeleniumTestSuites = array(); - -// include tests -// Todo: include automatically -if ( is_array( $wgSeleniumTestIncludes ) ) { - foreach ( $wgSeleniumTestIncludes as $include ) { - include_once $include; - } -} - -// run tests -foreach ( $wgSeleniumTestSuites as $suite ) { - $suite->run( $result ); +$suite = new SeleniumTestSuite; +foreach ( $wgSeleniumTests as $testClass ) { + $suite->addTest( new $testClass ); } +$suite->run( $result ); diff --git a/maintenance/tests/selenium/LocalSeleniumSettings.php.sample b/maintenance/tests/selenium/LocalSeleniumSettings.php.sample deleted file mode 100644 index 886c8f9f13..0000000000 --- a/maintenance/tests/selenium/LocalSeleniumSettings.php.sample +++ /dev/null @@ -1,51 +0,0 @@ - \ No newline at end of file diff --git a/maintenance/tests/selenium/Selenium.php b/maintenance/tests/selenium/Selenium.php index 19ebf2f923..7db805a102 100644 --- a/maintenance/tests/selenium/Selenium.php +++ b/maintenance/tests/selenium/Selenium.php @@ -4,21 +4,16 @@ * This is implemented as a singleton. */ -if ( !defined( 'MEDIAWIKI' ) || !defined( 'SELENIUMTEST' ) ) { - echo "This script cannot be run standalone"; - exit( 1 ); -} - class Selenium extends Testing_Selenium { protected static $_instance = null; public $isStarted = false; public static function getInstance() { global $wgSeleniumTestsBrowsers, $wgSeleniumTestsSeleniumHost, $wgSeleniumTestsUseBrowser; - global $wgSeleniumTestsWikiUrl, $wgSeleniumServerPort; + global $wgSeleniumServerPort; if ( null === self::$_instance ) { self::$_instance = new self( $wgSeleniumTestsBrowsers[$wgSeleniumTestsUseBrowser], - $wgSeleniumTestsWikiUrl, + self::getBaseUrl(), $wgSeleniumTestsSeleniumHost, $wgSeleniumServerPort ); } @@ -36,23 +31,27 @@ class Selenium extends Testing_Selenium { $this->isStarted = false; } + static function getBaseUrl() { + global $wgSeleniumTestsWikiUrl, $wgServer, $wgScriptPath; + if ( $wgSeleniumTestsWikiUrl ) { + return $wgSeleniumTestsWikiUrl; + } else { + return $wgServer . $wgScriptPath; + } + } + public function login() { - global $wgSeleniumTestsWikiUser, $wgSeleniumTestsWikiPassword, $wgSeleniumTestsWikiUrl, $wgVersion; + global $wgSeleniumTestsWikiUser, $wgSeleniumTestsWikiPassword; - $this->open( $wgSeleniumTestsWikiUrl . '/index.php?title=Special:Userlogin' ); + $this->open( self::getBaseUrl() . '/index.php?title=Special:Userlogin' ); $this->type( 'wpName1', $wgSeleniumTestsWikiUser ); $this->type( 'wpPassword1', $wgSeleniumTestsWikiPassword ); - if (version_compare($wgVersion, '1.15.2', '>=')) { - $this->click( "//input[@id='wpLoginAttempt']" ); - } else { - $this->click( "//input[@id='wpLoginattempt']" ); - } + $this->click( "//input[@id='wpLoginAttempt']" ); $value = $this->doCommand( 'assertTitle', array( 'Login successful*' ) ); } public function loadPage( $title, $action ) { - global $wgSeleniumTestsWikiUrl; - $this->open( $wgSeleniumTestsWikiUrl . '/index.php?title=' . $title . '&action=' . $action ); + $this->open( self::getBaseUrl() . '/index.php?title=' . $title . '&action=' . $action ); } // Prevent external cloning diff --git a/maintenance/tests/selenium/SeleniumLoader.php b/maintenance/tests/selenium/SeleniumLoader.php new file mode 100644 index 0000000000..8d5e77139a --- /dev/null +++ b/maintenance/tests/selenium/SeleniumLoader.php @@ -0,0 +1,9 @@ +assertRegExp( "/$text/", $innerHTML ); } -} \ No newline at end of file +} diff --git a/maintenance/tests/selenium/SeleniumTestConsoleLogger.php b/maintenance/tests/selenium/SeleniumTestConsoleLogger.php index c02ea83ab4..b6f5496ce9 100644 --- a/maintenance/tests/selenium/SeleniumTestConsoleLogger.php +++ b/maintenance/tests/selenium/SeleniumTestConsoleLogger.php @@ -1,8 +1,4 @@ '; + // if ( $mode == SeleniumTestSuite::RESULT_OK ) $out .= ''; $out .= htmlentities( $message ); - // if ( $mode == MW_TESTLOGGER_RESULT_OK ) $out .= ''; - if ( $mode != MW_TESTLOGGER_CONTINUE_LINE ) { + // if ( $mode == SeleniumTestSuite::RESULT_OK ) $out .= ''; + if ( $mode != SeleniumTestSuite::CONTINUE_LINE ) { $out .= "\n"; } echo $out; } -} \ No newline at end of file +} diff --git a/maintenance/tests/selenium/SeleniumTestHTMLLogger.php b/maintenance/tests/selenium/SeleniumTestHTMLLogger.php index 084a04b599..fb472174e3 100644 --- a/maintenance/tests/selenium/SeleniumTestHTMLLogger.php +++ b/maintenance/tests/selenium/SeleniumTestHTMLLogger.php @@ -1,22 +1,10 @@ - pre { + public function setHeaders() { + global $wgOut; + $wgOut->addHeadItem( 'selenium', ''; + ' ); } public function write( $message, $mode = false ) { + global $wgOut; $out = ''; - if ( $mode == MW_TESTLOGGER_RESULT_OK ) { + if ( $mode == SeleniumTestSuite::RESULT_OK ) { $out .= ''; } - $out .= htmlentities( $message ); - if ( $mode == MW_TESTLOGGER_RESULT_OK ) { + $out .= htmlspecialchars( $message ); + if ( $mode == SeleniumTestSuite::RESULT_OK ) { $out .= ''; } - if ( $mode != MW_TESTLOGGER_CONTINUE_LINE ) { + if ( $mode != SeleniumTestSuite::CONTINUE_LINE ) { $out .= '
'; } - echo $out; + $wgOut->addHTML( $out ); } -} \ No newline at end of file +} diff --git a/maintenance/tests/selenium/SeleniumTestListener.php b/maintenance/tests/selenium/SeleniumTestListener.php index 2dfb5649ad..7187c10316 100644 --- a/maintenance/tests/selenium/SeleniumTestListener.php +++ b/maintenance/tests/selenium/SeleniumTestListener.php @@ -1,8 +1,4 @@ logger->write( 'Testing ' . $test->getName() . ' ... ', - MW_TESTLOGGER_CONTINUE_LINE + SeleniumTestSuite::CONTINUE_LINE ); } public function endTest( PHPUnit_Framework_Test $test, $time ) { if ( !$test->hasFailed() ) { - $this->logger->write( 'OK', MW_TESTLOGGER_RESULT_OK ); + $this->logger->write( 'OK', SeleniumTestSuite::RESULT_OK ); $this->tests_ok++; } } diff --git a/maintenance/tests/selenium/SeleniumTestSuite.php b/maintenance/tests/selenium/SeleniumTestSuite.php index 381902c1f1..ca5e18283f 100644 --- a/maintenance/tests/selenium/SeleniumTestSuite.php +++ b/maintenance/tests/selenium/SeleniumTestSuite.php @@ -1,17 +1,13 @@ selenium = Selenium::getInstance(); $this->selenium->start(); diff --git a/maintenance/tests/selenium/SimpleSeleniumTest.php b/maintenance/tests/selenium/SimpleSeleniumTest.php index aaf276b4e3..5ee32cd0ea 100644 --- a/maintenance/tests/selenium/SimpleSeleniumTest.php +++ b/maintenance/tests/selenium/SimpleSeleniumTest.php @@ -1,31 +1,21 @@ addTest(new SimpleSeleniumTest()); - class SimpleSeleniumTest extends SeleniumTestCase { public $name = "Basic selenium test"; public function runTest() { - global $wgSeleniumTestsWikiUrl; - $this->open($wgSeleniumTestsWikiUrl.'/index.php?title=Selenium&action=edit'); - $this->type("wpTextbox1", "This is a basic test"); - $this->click("wpPreview"); - $this->waitForPageToLoad(10000); + $this->open( Selenium::getBaseUrl() . '/index.php?title=Selenium&action=edit' ); + $this->type( "wpTextbox1", "This is a basic test" ); + $this->click( "wpPreview" ); + $this->waitForPageToLoad( 10000 ); // check result - $source = $this->getText("//div[@id='wikiPreview']/p"); - $correct = strstr($source, "This is a basic test"); - $this->assertEquals($correct, true); + $source = $this->getText( "//div[@id='wikiPreview']/p" ); + $correct = strstr( $source, "This is a basic test" ); + $this->assertEquals( $correct, true ); } -} \ No newline at end of file +}