diff options
Diffstat (limited to 'test_tools/selenium/php/selenium.php')
-rw-r--r-- | test_tools/selenium/php/selenium.php | 477 |
1 files changed, 477 insertions, 0 deletions
diff --git a/test_tools/selenium/php/selenium.php b/test_tools/selenium/php/selenium.php new file mode 100644 index 00000000..9ad4955b --- /dev/null +++ b/test_tools/selenium/php/selenium.php @@ -0,0 +1,477 @@ +<?php +/** + * Selenium PHP driver. Saves the test command in a "out" queue (in session), + * and for each selenese request, remove the first comand from the "out" queue + * and push the results into the "in" queque (also in session). When "out" queque + * is empty, write the results to disk. + * + * Usage: See ../../example.php + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the BSD License. + * + * Copyright(c) 2004 by Wei Zhuo. All rights reserved. + * + * To contact the author write to {@link mailto:weizhuo[at]gmail[dot]com Wei Zhuo} + * The latest version of PRADO can be obtained from: + * {@link http://prado.sourceforge.net/} + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @version $Revision: 1.66 $ $Date: Wed Nov 02 10:13:17 EST 2005 10:13:17 $ + * @package Prado.tests + */ + +/** + * Selenium automatic client runner, + * + * @author Wei Zhuo<weizhuo[at]gmail[dot]com> + * @version $Revision: 1.66 $ $Date: Fri Nov 04 13:20:12 EST 2005 13:20:12 $ + * @package Prado.tests + */ + +require_once(dirname(__FILE__).'/results.php'); + +class SeleniumTestRunner +{ + protected $driver; + protected $base_dir = ''; + + public function __construct($driver=null, $base_dir='../javascript/') + { + if(is_null($driver) && !(php_sapi_name() == 'cli')) + $driver = $_SERVER['SCRIPT_NAME']; + $this->driver = $driver; + $this->base_dir = $base_dir; + } + + public function render() + { + if((php_sapi_name() == 'cli')) return; + $file = dirname(__FILE__).'/TestRunner.php'; + $driver = $this->driver; + + //$base_dir = $this->base_dir; + $base_dir = $driver.'?sr='; + include($file); + } + + public function getDriver() + { + return $this->driver; + } +} + +class SeleniumTestStorage +{ + protected $outputs = array(); + protected $tests = array(); + + public function getTests() + { + return $this->tests; + } + + public function addCommand($test_case_id, $command) + { + $data = array($test_case_id, $command); + array_push($this->outputs, $data); + } + + public function getCommand() + { + return array_shift($this->outputs); + } + + public function addTestCase($command, $trace_details, $test_name, $test_suite) + { + $data = array(0, 0, $command, "", $trace_details, $test_name, $test_suite); + array_push($this->tests, $data); + } +} + +class SeleneseInterpreter +{ + protected $storage; + protected $tracer; + + public function __construct($storage, $tracer) + { + $this->storage = $storage; + $this->tracer = $tracer; + } + + public function getTests() + { + return $this->storage->getTests(); + } + + public function getCommand() + { + $command = $this->storage->getCommand(); + return empty($command) ? "|testComplete|||" : "{$command[1]}<{$command[0]}>"; + } + + public function __call($func, $args) + { + if($func{0} == '_') return; + + $ID = isset($args[0]) ? $args[0] : ""; + $value = isset($args[1]) ? $args[1] : ""; + if(strpos(strtolower($func),'htmlpresent') || strpos(strtolower($func),'htmlnotpresent')) + $ID = htmlspecialchars($ID); + $command = array($func, $ID, $value); + $trace = debug_backtrace(); + + if(is_int(strpos(strtolower($func), 'visible'))) + $this->addCommand(array('pause','500',''),$trace); + + return $this->addCommand($command, $trace); + } + + protected function addCommand($command, $trace) + { + list($trace, $test, $suite) = $this->tracer->getTrace($trace); + $test_id = $this->storage->addTestCase($command, $trace, $test, $suite); + $this->storage->addCommand($test_id, $command); + } +} + +class SeleniumTestTrace +{ + protected $root; + + public function __construct($root) + { + $this->root = $root; + } + + public function getTrace($trace) + { + $group = array_pop($trace); + $info = $trace[3]; + $test = $group['args'][0]->getTestList(); + $i = count($test); + $name = $test[$i-2].'::'.$test[$i-1]; + $suite = $test[0]; + unset($info['object']); + /* + for($i = 0; $i < count($info['args']); $i++) + { + if($info['args'][$i] instanceof TControl) + $info['args'][$i] = $info['args'][$i]->ClientID; + }*/ + $file = str_replace($this->root, '', $info['file']); + $info['file'] = substr($file, 1); + return array($info, $name, $suite); + } +} + +class SimpleSeleniumProxyServer +{ + protected $runner; + protected $int; + protected $result_file; + + public function __construct($runner, $int, $result_file) + { + $this->int = $int; + $this->runner = $runner; + $this->result_file = $result_file; + } + + public function proxy() + { + return $this->int; + } + + + public static function getInstance($root='/', $result_file='results.dat', $base_dir='selenium/') + { + static $instance; + if(!isset($instance)) + { + $storage = new SeleniumTestStorage(); + $tracer = new SeleniumTestTrace($root); + $interpreter = new SeleneseInterpreter($storage, $tracer); + $runner = new SeleniumTestRunner(null, $base_dir); + $instance = new SimpleSeleniumProxyServer($runner, $interpreter, $result_file); + } + $instance->serveResults(); + return $instance; + } + + public function handleRequest() + { + $client = new SeleniumTestRunnerServer($this->int, $this->runner); + $client->serve(); + return true; + } + + public function serveResults() + { + if(isset($_POST['result'])) + { + $result = new SeleniumTestResult(); + $reporter = new SeleniumHtmlReporter($result); + $reporter->render(); + exit(); + } + } + +} + +class SeleniumTestSuiteWriter +{ + protected $suites; + protected $name; + protected $runner; + + function __construct($suites, $name, $runner) + { + $this->suites = $suites; + $this->name = $name; + $this->runner = $runner; + + } + + protected function renderHeader() + { + $contents = <<<EOD +<html> +<head> +<meta content="text/html; charset=UTF-8" http-equiv="content-type"> +<title>Test Suite</title> + +</head> + +<body> + +<table cellpadding="1" + cellspacing="1" + border="1"> + <tbody> + <tr><td><b>{$this->name}</b></td></tr> +EOD; + return $contents; + } + + public function render() + { + echo $this->renderHeader(); + foreach($this->suites as $name => $suite) + { + $file = $suite[0]['trace']['file']; + $file = strtr($file,'\\','/'); + $url = $this->runner->getDriver()."?case={$name}&file={$file}"; + echo "<tr>\n"; + echo "<td><a href=\"{$url}\">{$name}</a></td>\n"; + echo "</tr>\n"; + } + echo $this->renderFooter(); + } + + protected function getJsTraceInfo() + { + $contents = "var prado_trace = {};\n"; + foreach($this->suites as $name => $suite) + { + $name = $name; + $contents .= "prado_trace['{$name}'] = ["; + $cases = array(); + foreach($suite as $testcase) + $cases[] = "'".addslashes(htmlspecialchars(serialize($testcase['trace'])))."'"; + $contents .= implode(",\n", $cases)."];\n\n"; + } + return $contents; + } + + protected function renderFooter() + { + $trace = '';//$this->getJsTraceInfo(); + $contents = <<<EOD + </tbody> + </table> + <script type="text/javascript"> + /*<![CDATA[*/ + $trace + /*]]>*/ + </script> +</body> +</html> +EOD; + return $contents; + } +} + +class SeleniumTestCaseWriter +{ + protected $case; + protected $tests; + + function __construct($case, $tests) + { + $this->case = $case; + $this->tests = $tests; + } + + protected function renderHeader() + { + $contents = <<<EOD +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> +<title>{$this->case}</title> + <meta content="text/html; charset=UTF-8" http-equiv="content-type"> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1" id=TABLE1> + <tbody> + <tr> + <td rowspan="1" colspan="3"><strong>{$this->case}</strong></td> + </tr> +EOD; + return $contents; + } + + public function render() + { + echo $this->renderHeader(); + foreach($this->tests as $test) + { + $t = $test['test']; + if($t[0] == "open") + $t[1] = "<a href=\"{$t[1]}\" target=\"_blank\">{$t[1]}</a>"; + echo "<tr>\n"; + echo "<td>{$t[0]}</td>\n"; + echo "<td>{$t[1]}</td>\n"; + echo "<td>{$t[2]}</td>\n"; + echo "</tr>\n"; + } + echo $this->renderFooter(); + } + + protected function renderFooter() + { + $contents = <<<EOD + </tbody> +</table> +</body> +</html> +EOD; + return $contents; + } +} + +class SeleniumTestRunnerServer +{ + protected $cases = array(); + protected $trace = array(); + protected $name; + protected $runner; + + public function __construct($int, $runner) + { + $this->runner = $runner; + $this->initialize($int); + } + + protected function initialize($int) + { + foreach($int->getTests() as $command) + { + $case = $command[5]; + $this->cases[$case][] = + array('test' => $command[2], 'trace' => $command[4]); + if(is_null($this->name)) + $this->name = $command[6]; + } + } + + function serve() + { + if($this->isTestSuiteRequest()) + { + $testSuite = new SeleniumTestSuiteWriter($this->cases, + $this->name, $this->runner); + $testSuite->render(); + } + else if($this->isTestCaseRequest()) + { + if(($case = $this->getTestCaseRequest()) !== false) + { + + $testCase = new SeleniumTestCaseWriter($case, $this->getTestCase()); + $testCase->render(); + } + } + else + { + $this->runner->render(); + } + } + + protected function isTestSuiteRequest() + { + return isset($_GET['testSuites']); + } + + protected function isTestCaseRequest() + { + return isset($_GET['case']); + } + + public function isClientRequest() + { + return !$this->isTestSuiteRequest() && !$this->isTestCaseRequest(); + } + + protected function getTestCaseRequest() + { + $case = $_GET['case']; + if(isset($this->cases[$case])) + return $case; + else return false; + } + + protected function getTestCase() + { + $case = $_GET['case']; + if(isset($this->cases[$case])) + return $this->cases[$case]; + else + return array(); + } +} + + +class SeleniumTestCase extends UnitTestCase +{ + protected $selenium; + protected $Page; + + function __construct() + { + $server = SimpleSeleniumProxyServer::getInstance(); + if(!is_null($server)) + $this->selenium = $server->proxy(); + parent::__construct(); + } + + function getPage($class) + { + $info = new ReflectionClass($class); + return Prado::getApplication()->getTestPage($info->getFileName()); + } + + function __call($func, $args) + { + if(count($args) == 0) + return $this->selenium->{$func}(); + else if (count($args) == 1) + return $this->selenium->{$func}($args[0]); + else if (count($args) == 2) + return $this->selenium->{$func}($args[0], $args[1]); + } +} + +?>
\ No newline at end of file |