* @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 * @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; 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] : ""; //if($ID instanceof TControl) // $ID = $ID->ClientID; $value = isset($args[1]) ? $args[1] : ""; if(strpos(strtolower($func),'htmlpresent') || strpos(strtolower($func),'htmlnotpresent')) $ID = htmlspecialchars($ID); //$command = "|{$func}|{$ID}|{$value}|"; $command = array($func, $ID, $value); $trace = debug_backtrace(); 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// extends SeleniumProxyServer { 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() { $result = null; if(isset($_POST['result'])) { $result = new SeleniumTestResult(); file_put_contents($this->result_file, serialize($result)); } else if(isset($_GET['results'])) { if(is_file($this->result_file)) $result = unserialize(file_get_contents($this->result_file)); } if(!is_null($result)) { $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 = << Test Suite 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 "\n"; echo "\n"; echo "\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 = <<
{$this->name}
{$name}
EOD; return $contents; } } class SeleniumTestCaseWriter { protected $case; protected $tests; function __construct($case, $tests) { $this->case = $case; $this->tests = $tests; } protected function renderHeader() { $contents = << {$this->case} EOD; return $contents; } public function render() { echo $this->renderHeader(); foreach($this->tests as $test) { $t = $test['test']; if($t[0] == "open") $t[1] = "{$t[1]}"; echo "\n"; echo "\n"; echo "\n"; echo "\n"; echo "\n"; } echo $this->renderFooter(); } protected function renderFooter() { $contents = <<
{$this->case}
{$t[0]}{$t[1]}{$t[2]}
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]); } } ?>