|
|
(14 intermediate revisions by 2 users not shown) |
Line 1: |
Line 1: |
− | <?php
| + | {{legacy}} |
− | /**
| + | This extensions is composed of the following scripts: |
− | * Extension:Selenium{{php}}{{Category:Extensions|Selenium}}{{Category:Extensions in progress|Selenium}}
| + | *[[Selenium.php]] |
− | * {{Category:Selenium}}{{Category:Extensions created with Template:SpecialPage}}
| + | *[[Selenium.class.php]] |
− | * - Licenced under LGPL http://www.gnu.org/copyleft/lesser.html
| + | *[[SpecialSelenium.php]] |
− | * - Author: http://www.organicdesign.co.nz/User:Sven (M Davy)
| + | *[[postResults.php]] |
− | */
| |
| | | |
− | if (!defined('MEDIAWIKI')) die('Not an entry point.');
| + | == Notes == |
− | define('SELENIUM_VERSION', '0.8.0, 2008-08-01');
| + | * The [[mw:Extension:Selenium|extension documentation]] is hosted on http://mediawiki.org. |
− | | + | * [[Example Selenium test suite]] |
− | $egSeleniumTag = "selenium";
| + | [[Category:Legacy Extensions]] |
− | $egSeleniumPath = preg_replace('|^.+(?=[/\\\\]extensions)|', $wgScriptPath, dirname(__FILE__)) . 'selenium-core';
| |
− | $egResultsUrlPath = "../../tmp/results.php";
| |
− | $egSpecialPath = "/wiki/index.php?title=Special:Selenium&suite=";
| |
− | $egSeleniumCategory = "Selenium";
| |
− | $egSeleniumNamespace = "";
| |
− | | |
− | /**
| |
− | * http://www.mediawiki.org/wiki/Manual:Special_pages
| |
− | * $wgSpecialPages['Selenium'] = 'Selenium';
| |
− | */
| |
− | | |
− | $wgExtensionFunctions[] = 'efSetupSelenium';
| |
− | $wgHooks['LanguageGetMagic'][] = 'efSeleniumLanguageGetMagic';
| |
− | | |
− | $wgExtensionCredits['specialpage'][] = array(
| |
− | 'name' => 'Special:Selenium',
| |
− | 'author' => '[http://www.organicdesign.co.nz/User:Sven Sven (M Davy)]',
| |
− | 'description' => 'Incorporating Selenium tests into the MediaWiki environment',
| |
− | 'url' => 'http://www.organicdesign.co.nz/Extension:Selenium.php',
| |
− | 'version' => SELENIUM_VERSION
| |
− | );
| |
− | | |
− | require_once "$IP/includes/SpecialPage.php";
| |
− | | |
− | # Define the seleium tag class
| |
− | class Selenium {
| |
− |
| |
− | # Properties
| |
− | | |
− | # Constructor
| |
− | function __construct() {
| |
− | global $wgHooks,$wgParser,$egSeleniumTag;
| |
− | | |
− | # Add the tagHook
| |
− | $wgParser->setHook($egSeleniumTag,array($this,'tagSelenium'));
| |
− | }
| |
− | | |
− | /**
| |
− | * Deploy tags to allow additional html table tags
| |
− | */
| |
− | public function tagSelenium($text, $argv, &$parser) {
| |
− | global $wgTitle, $egSeleniumCategory;
| |
− | | |
− | /**
| |
− | * Should be a preprocess using first stage of parser
| |
− | * $text = $parser->preprocess($text,$wgTitle,$parser->mOptions);
| |
− | */
| |
− | | |
− | /**
| |
− | * Want the Selenium tag to strip out <html>...</html> enclosing tags
| |
− | * It currently removes everything around the first <table...</table> tags found
| |
− | */
| |
− | | |
− | $text = eregi_replace('<html>.+<table', '<div class="selenium"><table', $text);
| |
− | $text = eregi_replace('</table>.+', '</table></div>', $text);
| |
− | | |
− | # Automatically create category as specified in $egSeleniumCategory
| |
− | if($egSeleniumCategory) {
| |
− | $this->magicCategory($parser, $egSeleniumCategory, $sortkey = '');
| |
− | }
| |
− | | |
− | # We have not run htmlspecialchars to minimize cross-site scripting vulnerabilities
| |
− | return($text);
| |
− | }
| |
− | | |
− | # Expand the category-magic to nothing and parse separately as normal category links
| |
− | private function magicCategory(&$parser, $cat, $sortkey = '') {
| |
− | if ($sortkey) $sortkey = "|$sortkey";
| |
− | $parser->parse("[[Category:$cat$sortkey]]", $parser->mTitle, $parser->mOptions, false, false);
| |
− | return '';
| |
− | }
| |
− | | |
− | /**
| |
− | * Needed in some versions to prevent Special:Version from breaking
| |
− | */
| |
− | private function __toString() {
| |
− | return __CLASS__;
| |
− | }
| |
− | }
| |
− | | |
− | | |
− | /**
| |
− | * Define a new class based on the SpecialPage class
| |
− | */
| |
− | class SpecialSelenium extends SpecialPage {
| |
− | | |
− | /**
| |
− | * Need a global for the location of Selenium
| |
− | */
| |
− |
| |
− | # Properties
| |
− | var $suite = array(
| |
− | 'header' => '<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">
| |
− | <title>Selenium</title></head><body><table cellpadding="1" cellspacing="1" border="1"><tbody>',
| |
− | 'footer' => "\n</tbody></table></body></html>"
| |
− | );
| |
− |
| |
− | /**
| |
− | * Constructor
| |
− | */
| |
− | function __construct() {
| |
− | SpecialPage::SpecialPage(
| |
− | 'Selenium', # name as seen in links etc
| |
− | '', # user rights required
| |
− | true, # listed in special:specialpages
| |
− | false, # function called by execute() - defaults to wfSpecial{$name}
| |
− | false, # file included by execute() - defaults to Special{$name}.php, only used if no function
| |
− | false # includable
| |
− | );
| |
− | }
| |
− |
| |
− | /**
| |
− | * -------------------- Create form for Special:Selenium --------------------
| |
− | * Override SpecialPage::execute()
| |
− | */
| |
− | public function execute() {
| |
− | global $wgOut, $wgParser, $wgRequest, $egResultsUrlPath;
| |
− | | |
− | # Process suite or test if ?suite=article_name in query string
| |
− | if ($wgRequest->getText('suite')) {
| |
− | | |
− | # Grab article $param and process contents
| |
− | $suiteTitle = Title::newFromText($wgRequest->getText('suite'));
| |
− | | |
− | # print $suiteTitle;
| |
− | # print $suiteTitle->getText();
| |
− | # print $wgRequest->getText('suite');
| |
− | | |
− | $wikitext = $this->fetchContents($suiteTitle);
| |
− | # Expanding braces of any transcluded tests
| |
− | $wikitext = $wgParser->preprocess($wikitext, $suiteTitle, new ParserOptions());
| |
− | | |
− | # Preparse encapsulations around Selenium tags e.g. <nowiki><selenium></nowiki>
| |
− | $wikitext = preg_replace("|<nowiki></?selenium></nowiki>|", "<nowiki><selenium></nowiki>", $wikitext);
| |
− | | |
− | $matches = array();
| |
− | if (!$this->articleRegex($wikitext, $matches)) {
| |
− | $this -> build404('Specified suite contains no selenium test tags');
| |
− | }
| |
− | else {
| |
− | | |
− | # Determine whether suite or test from ?suite=article_name&test=section_num in query string
| |
− | | |
− | if ($wgRequest->getText('test')) {
| |
− | # Grab name of test
| |
− | $testTitle = Title::newFromText($wgRequest->getText('test'));
| |
− | if (in_array($testTitle->getText(), $matches[1])) {
| |
− | $counter = 0;
| |
− | foreach ($matches[1] as $value) {
| |
− | if ($value == $testTitle->getText()) {
| |
− | # Generating test html
| |
− | $matches[2][$counter] = preg_replace(
| |
− | '|.+?<selenium>\n?(.+?)</selenium>|ms',
| |
− | "$1",
| |
− | $matches[2][$counter]
| |
− | );
| |
− | print $matches[2][$counter];
| |
− | break; #exit foreach loop when test is found
| |
− | }
| |
− | $counter++;
| |
− | }
| |
− | }
| |
− | else $this -> build404("Specified test does not exist in " . $wgRequest->getText('suite'));
| |
− | }
| |
− | else {
| |
− | # Obtain suite section headers
| |
− | $suite_urls = array();
| |
− | foreach ($matches[1] as $value) array_push($suite_urls, $value);
| |
− | print $this->buildSuite($suite_urls, $wgRequest->getText('suite'));
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | else {
| |
− | global $egSeleniumCategory;
| |
− | | |
− | # Retrieve articles in category labelled $egSeleniumCategory
| |
− | $list = $this->categoryArticles($egSeleniumCategory);
| |
− | | |
− | # Grab article $param and process contents
| |
− | $suites = array();
| |
− | foreach ($list as $articleName) {
| |
− | $suiteTitle = Title::newFromText($articleName);
| |
− | $wikitext = $this->fetchContents($suiteTitle);
| |
− | if ($this->articleRegex($wikitext, $matches)) $suites[] = $articleName;
| |
− | }
| |
− |
| |
− | $selectTag = '<select name="selenium">';
| |
− | foreach($suites as $suite) $selectTag .= "<option>$suite</option>";
| |
− | $selectTag .= '</select>';
| |
− | | |
− | $this->setHeaders();
| |
− | $title = Title::makeTitle(NS_SPECIAL, 'Selenium');
| |
− | | |
− | global $egSeleniumPath, $egSpecialPath;
| |
− | $path = "$egSeleniumPath?test=" . urlencode($egSpecialPath);
| |
− | | |
− | $form = wfElement('form',array('action' => $title->getLocalURL('action=submit'),'method' => 'post'),null);
| |
− | $form .= '<fieldset><legend>Select a suite to run</legend>';
| |
− | $form .= $selectTag;
| |
− | $form .= wfElement('input',array('type' => 'submit'));
| |
− | $form .= "<br /><br />" . wfCheckLabel("Run automatically","wfRunAuto" , "wfRunAuto",$checked = false);
| |
− | $form .= '</fieldset></form>';
| |
− | | |
− | $wgOut->addHTML($form);
| |
− | | |
− | if ($wgRequest->getText('action')) {
| |
− | # foreach($_REQUEST as $key=>$value) {
| |
− | # print "$key>$value" . "<br />";
| |
− | }
| |
− | $path .= urlencode($wgRequest->getText('selenium'));
| |
− | | |
− | if ($wgRequest->getBool('wfRunAuto')) $path .= "&auto=true&resultsUrl=$egResultsUrlPath";
| |
− | | |
− | $form_link = '<fieldset><legend>Click link to run selenium-core</legend>';
| |
− | $form_link .= "<a href=\"$path\">" . $wgRequest->getText('selenium') . '</a></fieldset>';
| |
− | $wgOut->addHTML($form_link);
| |
− | }
| |
− | }
| |
− | | |
− | private function categoryArticles($category) {
| |
− | $list = array();
| |
− | $dbr = &wfGetDB(DB_SLAVE);
| |
− | $cl = $dbr->tableName('categorylinks');
| |
− | $res = $dbr->select($cl, 'cl_from', "cl_to = '$category'", __METHOD__, array('ORDER BY' => 'cl_sortkey'));
| |
− | while ($row = $dbr->fetchRow($res)) {
| |
− | $list[] = Title::newFromID($row[0])->getPrefixedText();
| |
− | }
| |
− | return $list;
| |
− | }
| |
− | | |
− | private function fetchContents($title) {
| |
− | $article = new Article($title);
| |
− | $contents = $article->getContent();
| |
− | return $contents;
| |
− | }
| |
− | | |
− | private function articleRegex(&$wikitext, &$matches) {
| |
− | return preg_match_all('|^={2,}\s*([^\#\<\>\[\]\|\{\}\n]+?)\s*={2,}(.+?</selenium>)|ms', $wikitext, $matches);
| |
− | }
| |
− | | |
− | /**
| |
− | * Method to bypass $wgOut -must be called early to avoid conflict with other extensions
| |
− | */
| |
− | static function disableHTML(&$wgOut) {
| |
− | $wgOut->disable();
| |
− | wfResetOutputBuffers();
| |
− | return;
| |
− | }
| |
− | | |
− | /**
| |
− | * Method to generate 404 error
| |
− | */
| |
− | private function build404($message) {
| |
− | header('HTTP/1.0 404 not Found');
| |
− | $err = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\"><html><head><title>404 Error</title></head>
| |
− | <body><h1>$message</h1><p>The requested URL was not found on this server.</p></body></html>";
| |
− | print $err;
| |
− | return;
| |
− | }
| |
− | | |
− | /**
| |
− | * Method to build a suite from an array of tests
| |
− | */
| |
− | private function buildSuite($tests, $article) {
| |
− | | |
− | $html = $this->suite['header'];
| |
− | $html .= "<tr><td><b>$article</b></td></tr>";
| |
− | foreach ($tests as $element) {
| |
− | $html .= "\n<tr><td><a href=\"/wiki/index.php?title=Special:Selenium&suite=$article&test=$element\">$element</a></td></tr>";
| |
− | }
| |
− | | |
− | $html .= $this->suite['footer'];
| |
− | return $html;
| |
− | }
| |
− | }
| |
− | | |
− | /**
| |
− | * Called from $wgExtensionFunctions array when initialising extensions
| |
− | */
| |
− | function efSetupSelenium() {
| |
− | global $wgRequest, $wgOut, $egSelenium, $wgLanguageCode, $wgMessageCache;
| |
− | | |
− | # Process suite or test if ?suite=article_name in query string
| |
− | if ($wgRequest->getText('suite')) {
| |
− | SpecialSelenium::disableHTML($wgOut); # Render only Selenium html
| |
− | }
| |
− | | |
− | $egSelenium = new Selenium();
| |
− | | |
− | # Add the messages used by the specialpage
| |
− | if ($wgLanguageCode == 'en') {
| |
− | $wgMessageCache->addMessages(array(
| |
− | 'selenium' => 'Selenium testing environment' # The friendly page title
| |
− | ));
| |
− | }
| |
− | | |
− | # Add the specialpage to the environment
| |
− | SpecialPage::addPage(new SpecialSelenium());
| |
− | }
| |
− | | |
− | /**
| |
− | * Needed in MediaWiki >1.8.0 for magic word hooks to work properly
| |
− | */
| |
− | function efSeleniumLanguageGetMagic(&$magicWords, $langCode = 0) {
| |
− | global $egSeleniumMagic;
| |
− | $magicWords[$egSeleniumMagic] = array($langCode, $egSeleniumMagic);
| |
− | return true;
| |
− | }
| |