Difference between revisions of "Selenium.class.php"
From Organic Design wiki
| m | m | ||
| Line 1: | Line 1: | ||
| {{legacy}} | {{legacy}} | ||
| − | <php><?php | + | <source lang="php"><?php | 
| /** | /** | ||
|   * Selenium extension |   * Selenium extension | ||
| Line 157: | Line 157: | ||
| 	} | 	} | ||
| } | } | ||
| − | </ | + | </source> | 
Latest revision as of 14:56, 27 February 2020
<?php
/**
 * Selenium extension
 *
 * See http://www.mediawiki.org/Extension:Selenium for installation and usage details
 * See http://www.organicdesign.co.nz/Extension_talk:Selenium.php for development notes and disucssion
 * 
 * @package MediaWiki
 * @subpackage Extensions
 * @author Marcus Davy [http://www.organicdesign.co.nz/User:Sven User:Sven]
 * @copyright © 2007 Marcus Davy
 * @licence GNU General Public Licence 2.0 or later
 */
if (!defined('MEDIAWIKI')) die('Not an entry point.');
class Selenium {
	var $testCount = array(); # keep track of number of tests in each suite processed
	function __construct() {
		global $wgParser, $egSeleniumTag;
		# Add the tag hook
		$wgParser->setHook($egSeleniumTag, array($this, 'tagSelenium'));
		# Check the schedule and see if any test-runs should be spawned
		$this->checkSchedule();
	}
	/**
	 * Process a selenium tag with test syntax in it
	 * - this tag also handles the categorisation of the article into Category:Selenium
	 */
	public function tagSelenium($text, &$argv, &$parser) {
		global $wgOut, $egSeleniumSuiteCat, $egSeleniumTestCat;
		# The suite being processed is the article title text, keep track of number of tests in it
		$suite = $parser->mTitle->getPrefixedText();
		$this->testCount[$suite] = array_key_exists($suite, $this->testCount) ? $this->testCount[$suite]+1 : 1;
		
		# Get name of test from title tag
		$name = preg_match("|<title>(.+?)</title>|i", $text, $match) ? $match[1] : 'untitled';
		# Get rid of unwanted tags
		$text = preg_replace("#\\s*<head>.+</head>\\s*#is", "", $text);
		$text = preg_replace("#\\s*</?t?(html|head|body)>\\s*#i", "", $text);
		# Categorise the article into Selenium tests category if more than one test in this suite
		# - todo: and also remove from the cat for individual tests
		if ($this->testCount[$suite] > 1) $text .= "[[Category:$egSeleniumSuiteCat]]";
		# Parse the content normally and return wrapped in a div of class selenium and id of test name
		$out = $parser->parse($text, $parser->mTitle, $parser->mOptions, false, false);
		$text = $out->getText();
		return "<div class=\"selenium\" id=\"$name\">$text</div><!-- selenium-end -->";
	}
	/**
	 * Extract the individual tests from the suite indexed by name in selenese HTML format
	 * - also add the selenese HTML for the whole suite under index of suite name
	 */
	public static function selenese($suite, $path = false) {
		global $wgParser;
		# Get the content of the suite article and parse it
		# NOTE: parsing the content results in the head, body, thead, tbody etc being removed,
		#       but it seems that the TestRunner doesn't care and can work with the basic table structure
		$suiteTitle = Title::newFromText($suite);
		$suiteArticle = new Article($suiteTitle);
		$text = $wgParser->parse($suiteArticle->getContent(), $suiteTitle, new ParserOptions(), true, true)->getText();
		# extract the name and content of the individual tests in the suite
		$numTests = preg_match_all(
			"|<div class=\"selenium\" id=\"(.+?)\">\\s*(.+?)\\s*</div><!-- selenium-end -->|is",
			$text,
			$matches,
			PREG_PATTERN_ORDER
		);
		# Re-organise the matched test content into a hash indexed by test name
		$tests = array();
		for ($i = 0; $i < $numTests; $i++) $tests[$matches[1][$i]] = $matches[2][$i];
		
		# Create the HTML for the entire suite under index of suite name
		$html = "<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><tr><td><b>$suite</b></td></tr>\n";
		$title = Title::makeTitle(NS_SPECIAL, 'Selenium');
		foreach (array_keys($tests) as $test) {
			$url = $path ? "$path/wiki-".urlencode($test).".html" : $title->getLocalURL("suite=$suite&test=$test");
			$html .= "<tr><td><a href=\"$url\">$test</a></td></tr>\n";
		}
		$tests[$suite] = "$html</tbody></table></body></html>";
		
		return $tests;
	}
	/**
	 * Check whether any tests should run
	 */
	public function checkSchedule() {
		global $egSeleniumSchdeule;
		if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'runtests') $this->runTests();
		$ts = date('H:i');
		if (in_array($ts, $egSeleniumSchdeule)) {
			$ts = date('d M Y').", $ts";
			# Get the last log entry
			# If tests for this time and day haven't run yet, run them now
			if ("Last log entry time stamp not equal to current") $this->runTests();
		}
	}
	/**
	 * Run all the tests in the schedule in Selenium Remote Control (SRC)
	 */
	public function runTests() {
		global $IP, $egSeleniumSchedule, $egSeleniumPath, $egSeleniumDir;
		
		# Update the log with tests start message
		
		# Define paths for the java server, the HTML test files and the results file
		$jar   = "$egSeleniumDir/selenium-server/selenium-server.jar";
		$tests = "$egSeleniumDir/selenium-core/tests";
		$out   = "$egSeleniumDir/selenium-core/tests/results.txt";
		# We need to flip the operation to work by domain on the outer loop
		# - because it needs to build a set of selenese suite/test files for each site
		#   since the parser-functions used in the tests must be resolved my the wiki being tested
		foreach ($egSeleniumSchedule as $suite => $domains) if (!is_numeric($suite)) {
			$es = urlencode($suite);
			# Copy the suite and its tests as selenese HTML into the place SRC expects to find them
			foreach (Selenium::selenese($suite, "/selenium-server/tests") as $k => $v) {
				$ek = urlencode($k);
				file_put_contents("$tests/wiki-$ek.html", $v);
			}
			# Run the suite for each domain
			foreach ($domains as $domain) {
				shell_exec("java -jar $jar -htmlSuite \"*custom /usr/bin/firefox\" \"$domain\" \"$tests/wiki-$es.html\" \"$out\"");
				$results = file_get_contents($out);
			}
		}
		
		# Update the log with test results
	}
	/**
	 * Needed in some versions to prevent Special:Version from breaking
	 */
	private function __toString() {
		return __CLASS__;
	}
}








