Merge branch '2.0' into 2.0-request

This commit is contained in:
mark_story 2010-07-15 23:43:48 -04:00
commit 90091aed48
33 changed files with 1168 additions and 360 deletions

View file

@ -155,9 +155,15 @@ class ShellDispatcher {
if (!defined('CAKE_CORE_INCLUDE_PATH')) { if (!defined('CAKE_CORE_INCLUDE_PATH')) {
define('DS', DIRECTORY_SEPARATOR); define('DS', DIRECTORY_SEPARATOR);
define('CAKE_CORE_INCLUDE_PATH', dirname(dirname(dirname(__FILE__)))); define('CAKE_CORE_INCLUDE_PATH', dirname(dirname(dirname(__FILE__))));
define('CORE_PATH', CAKE_CORE_INCLUDE_PATH . DS);
define('DISABLE_DEFAULT_ERROR_HANDLING', false); define('DISABLE_DEFAULT_ERROR_HANDLING', false);
define('CAKEPHP_SHELL', true); define('CAKEPHP_SHELL', true);
if (!defined('CORE_PATH')) {
if (function_exists('ini_set') && ini_set('include_path', CAKE_CORE_INCLUDE_PATH . PATH_SEPARATOR . ini_get('include_path'))) {
define('CORE_PATH', null);
} else {
define('CORE_PATH', CAKE_CORE_INCLUDE_PATH . DS);
}
}
} }
require_once(CORE_PATH . 'cake' . DS . 'basics.php'); require_once(CORE_PATH . 'cake' . DS . 'basics.php');
} }

View file

@ -42,10 +42,10 @@ class TestSuiteShell extends Shell {
} else { } else {
define('TEST_CAKE_CORE_INCLUDE_PATH', CAKE_CORE_INCLUDE_PATH); define('TEST_CAKE_CORE_INCLUDE_PATH', CAKE_CORE_INCLUDE_PATH);
} }
$params = $this->parseArgs();
$this->_dispatcher = new CakeTestSuiteDispatcher(); $this->_dispatcher = new CakeTestSuiteDispatcher();
$this->_dispatcher->setParams($params); $this->_dispatcher->loadTestFramework();
require_once CAKE . 'tests' . DS . 'lib' . DS . 'test_manager.php';
} }
/** /**
@ -53,7 +53,7 @@ class TestSuiteShell extends Shell {
* *
* @return array Array of params for CakeTestDispatcher * @return array Array of params for CakeTestDispatcher
*/ */
public function parseArgs() { protected function parseArgs() {
if (empty($this->args)) { if (empty($this->args)) {
return; return;
} }
@ -61,9 +61,6 @@ class TestSuiteShell extends Shell {
'app' => false, 'app' => false,
'plugin' => null, 'plugin' => null,
'output' => 'text', 'output' => 'text',
'codeCoverage' => false,
'filter' => false,
'case' => null
); );
$category = $this->args[0]; $category = $this->args[0];
@ -75,20 +72,32 @@ class TestSuiteShell extends Shell {
} }
if (isset($this->args[1])) { if (isset($this->args[1])) {
$params['case'] = Inflector::underscore($this->args[1]) . '.test.php'; $params['case'] = Inflector::underscore($this->args[1]);
}
if (isset($this->args[2]) && $this->args[2] == 'cov') {
$params['codeCoverage'] = true;
} }
if (isset($this->params['filter'])) { if (isset($this->params['filter'])) {
$params['filter'] = $this->params['filter']; $this->params['-filter'] = $this->params['filter'];
}
if (isset($this->params['coverage'])) {
$params['codeCoverage'] = true;
} }
return $params; return $params;
} }
/**
* Converts the options passed to the shell as options for the PHPUnit cli runner
*
* @return array Array of params for CakeTestDispatcher
*/
protected function runnerOptions() {
$options = array();
foreach ($this->params as $param => $value) {
if ($param[0] === '-') {
$options[] = '-' . $param;
if (is_string($value)) {
$options[] = $value;
}
}
}
return $options;
}
/** /**
* Main entry point to this shell * Main entry point to this shell
* *
@ -98,16 +107,86 @@ class TestSuiteShell extends Shell {
$this->out(__('CakePHP Test Shell')); $this->out(__('CakePHP Test Shell'));
$this->hr(); $this->hr();
if (count($this->args) == 0) { $args = $this->parseArgs();
$this->error(__('Sorry, you did not pass any arguments!'));
if (empty($args['case'])) {
$this->available();
} }
$result = $this->_dispatcher->dispatch(); $this->run($args, $this->runnerOptions());
$exit = 0; }
if ($result instanceof PHPUnit_Framework_TestResult) {
$exit = ($result->errorCount() + $result->failureCount()) > 0; /**
* Runs the test case from $runnerArgs
*
* @param array $runnerArgs list of arguments as obtained from parseArgs()
* @param array $options list of options as constructed by runnerOptions()
* @return void
*/
protected function run($runnerArgs, $options = array()) {
require_once CAKE . 'tests' . DS . 'lib' . DS . 'test_runner.php';
$testCli = new TestRunner($runnerArgs);
$testCli->run($options);
}
/**
* Shows a list of available test cases and gives the option to run one of them
*
* @return void
*/
public function available() {
$params = $this->parseArgs();
$testCases = TestManager::getTestCaseList($params);
$app = $params['app'];
$plugin = $params['plugin'];
$title = "Core Test Cases:";
$category = 'core';
if ($app) {
$title = "App Test Cases:";
$category = 'app';
} elseif ($plugin) {
$title = Inflector::humanize($plugin) . " Test Cases:";
$category = $plugin;
}
if (empty($testCases)) {
$this->out(__("No test cases available \n\n"));
$this->help();
$this->_stop();
}
$this->out($title);
$i = 1;
$cases = array();
foreach ($testCases as $testCaseFile => $testCase) {
$case = explode(DS, str_replace('.test.php', '', $testCase));
$case[count($case) - 1] = Inflector::camelize($case[count($case) - 1]);
$case = implode('/', $case);
$this->out("[$i] $case");
$cases[$i] = $case;
$i++;
}
while ($choice = $this->in(__('What test case would you like to run?'), null, 'q')) {
if (is_numeric($choice) && isset($cases[$choice])) {
$this->args[0] = $category;
$this->args[1] = $cases[$choice];
$this->run($this->parseArgs(), $this->runnerOptions());
break;
}
if (is_string($choice) && in_array($choice, $cases)) {
$this->args[0] = $category;
$this->args[1] = $choice;
$this->run($this->parseArgs(), $this->runnerOptions());
break;
}
if ($choice == 'q') {
break;
}
} }
$this->_stop($exit);
} }
/** /**
@ -116,36 +195,76 @@ class TestSuiteShell extends Shell {
* @return void * @return void
*/ */
public function help() { public function help() {
$help = <<<TEXT $this->out('CakePHP Testsuite:');
Usage: $this->hr();
-----
cake testsuite <category> <file> [params]
- category - "app", "core" or name of a plugin
- file - file name with folder prefix and without the test.php suffix.
Params: $this->out('The CakPHP Testsuite allows you to run test cases from the command line');
------- $this->out('If run with no command line arguments, a list of available core test cases will be shown');
-filter $this->hr();
The -filter option allows you supply a pattern that is used to match
test method names. This can be a regular expression.
-coverage $this->out("Usage: cake testuite <category> <file> [params]");
Enable code coverage for this run. $this->out("\t- category: app, core or name of a plugin");
$this->out("\t- file: file name with folder prefix and without the test.php suffix");
$this->hr();
Examples: $this->out("Usage: cake testuite available <category> [params]");
--------- $this->out("\t Shows a list of available testcases for the specified category");
cake testsuite app behaviors/debuggable; $this->out("\t Params list will be used for running the selected test case");
cake testsuite app models/my_model; $this->hr();
cake testsuite app controllers/my_controller
cake testsuite core libs/file $this->out('Examples:');
cake testsuite core libs/router $this->out('cake testsuite app models/my_model');
cake testsuite core libs/set $this->out("cake testsuite app controllers/my_controller \n");
$this->out('cake testsuite core libs/file');
$this->out("cake testsuite core libs/set \n");
$this->out('cake testsuite bugs models/bug -- for the plugin bugs and its test case models/bug');
$this->hr();
cake testsuite bugs models/bug $this->out('Params:');
// for the plugin 'bugs' and its test case 'models/bug' $this->out("--log-junit <file> Log test execution in JUnit XML format to file.");
$this->out("--log-json <file> Log test execution in JSON format.");
TEXT; $this->out("--coverage-html <dir> Generate code coverage report in HTML format.");
$this->out($help); $this->out("--coverage-clover <file> Write code coverage data in Clover XML format.");
$this->out("--coverage-source <dir> Write code coverage / source data in XML format.");
$this->out("--story-html <file> Write Story/BDD results in HTML format to file.");
$this->out("--story-text <file> Write Story/BDD results in Text format to file.");
$this->out("--testdox-html <file> Write agile documentation in HTML format to file.");
$this->out("--testdox-text <file> Write agile documentation in Text format to file.");
$this->out("--filter <pattern> Filter which tests to run.");
$this->out("--group ... Only runs tests from the specified group(s).");
$this->out("--exclude-group ... Exclude tests from the specified group(s).");
$this->out("--filter <pattern> Filter which tests to run.");
$this->out("--loader <loader> TestSuiteLoader implementation to use.");
$this->out("--repeat <times> Runs the test(s) repeatedly.");
$this->out("--story Report test execution progress in Story/BDD format.");
$this->out("--tap Report test execution progress in TAP format.");
$this->out("--testdox Report test execution progress in TestDox format.");
$this->out("--colors Use colors in output.");
$this->out("--stderr Write to STDERR instead of STDOUT.");
$this->out("--stop-on-failure Stop execution upon first error or failure.");
$this->out("--verbose Output more verbose information.");
$this->out("--wait Waits for a keystroke after each test.");
$this->out("--skeleton-class Generate Unit class for UnitTest in UnitTest.php.");
$this->out("--skeleton-test Generate UnitTest class for Unit in Unit.php.");
$this->out("--process-isolation Run each test in a separate PHP process.");
$this->out("--no-globals-backup Do not backup and restore \$GLOBALS for each test.");
$this->out("--static-backup Backup and restore static attributes for each test.");
$this->out("--syntax-check Try to check source files for syntax errors.");
$this->out("--bootstrap <file> A \"bootstrap\" PHP file that is run before the tests.");
$this->out("--configuration <file> Read configuration from XML file.");
$this->out("--no-configuration Ignore default configuration file (phpunit.xml).");
$this->out("--include-path <path(s)> Prepend PHP's include_path with given path(s).");
$this->out("-d key[=value] Sets a php.ini value. \n");
} }
} }

View file

@ -328,7 +328,7 @@ class Dispatcher {
); );
if (($isCss && empty($filters['css'])) || ($isJs && empty($filters['js']))) { if (($isCss && empty($filters['css'])) || ($isJs && empty($filters['js']))) {
header('HTTP/1.1 404 Not Found'); $this->header('HTTP/1.1 404 Not Found');
return $this->_stop(); return $this->_stop();
} elseif ($isCss) { } elseif ($isCss) {
include WWW_ROOT . DS . $filters['css']; include WWW_ROOT . DS . $filters['css'];
@ -394,11 +394,11 @@ class Dispatcher {
} }
} }
header("Date: " . date("D, j M Y G:i:s ", filemtime($assetFile)) . 'GMT'); $this->header("Date: " . date("D, j M Y G:i:s ", filemtime($assetFile)) . 'GMT');
header('Content-type: ' . $contentType); $this->header('Content-type: ' . $contentType);
header("Expires: " . gmdate("D, j M Y H:i:s", time() + DAY) . " GMT"); $this->header("Expires: " . gmdate("D, j M Y H:i:s", time() + DAY) . " GMT");
header("Cache-Control: cache"); $this->header("Cache-Control: cache");
header("Pragma: cache"); $this->header("Pragma: cache");
if ($ext === 'css' || $ext === 'js') { if ($ext === 'css' || $ext === 'js') {
include($assetFile); include($assetFile);
@ -411,4 +411,15 @@ class Dispatcher {
ob_end_flush(); ob_end_flush();
} }
} }
/**
* Sends the specified headers to the client
*
* @param string $header header to send
* @todo Refactor this to use a response object or similar
* @return void
*/
public function header($header) {
header($header);
}
} }

View file

@ -620,13 +620,7 @@ class Controller extends Object {
} }
$cached = false; $cached = false;
$object = null; $object = null;
$plugin = null; list($plugin, $modelClass) = pluginSplit($modelClass, true);
if ($this->uses === false) {
if ($this->plugin) {
$plugin = $this->plugin . '.';
}
}
list($plugin, $modelClass) = pluginSplit($modelClass, true, $plugin);
if ($this->persistModel === true) { if ($this->persistModel === true) {
$cached = $this->_persist($modelClass, null, $object); $cached = $this->_persist($modelClass, null, $object);

View file

@ -462,16 +462,16 @@ class Model extends Object {
$this->Behaviors = new BehaviorCollection(); $this->Behaviors = new BehaviorCollection();
if ($this->useTable !== false) { if ($this->useTable !== false) {
$this->setDataSource($ds);
if ($this->useTable === null) { if ($this->useTable === null) {
$this->useTable = Inflector::tableize($this->name); $this->useTable = Inflector::tableize($this->name);
} }
$this->setSource($this->useTable);
if ($this->displayField == null) { if ($this->displayField == null) {
$this->displayField = $this->hasField(array('title', 'name', $this->primaryKey)); unset($this->displayField);
} }
$this->table = $this->useTable;
$this->tableToModel[$this->table] = $this->alias;
} elseif ($this->table === false) { } elseif ($this->table === false) {
$this->table = Inflector::tableize($this->name); $this->table = Inflector::tableize($this->name);
} }
@ -492,11 +492,87 @@ class Model extends Object {
if ($result !== array('unhandled')) { if ($result !== array('unhandled')) {
return $result; return $result;
} }
$db =& ConnectionManager::getDataSource($this->useDbConfig); $return = $this->getDataSource()->query($method, $params, $this);
$return = $db->query($method, $params, $this);
return $return; return $return;
} }
/**
* Handles the lazy loading of model associations by lookin in the association arrays for the requested variable
*
* @param string $name variable tested for existance in class
* @return boolean true if the variable exists (if is a not loaded model association it will be created), false otherwise
*/
public function __isset($name) {
$className = false;
foreach ($this->__associations as $type) {
if (isset($name, $this->{$type}[$name])) {
$className = empty($this->{$type}[$name]['className']) ? $name : $this->{$type}[$name]['className'];
break;
} else if ($type == 'hasAndBelongsToMany') {
foreach ($this->{$type} as $k => $relation) {
if (empty($relation['with'])) {
continue;
}
if (is_array($relation['with'])) {
if (key($relation['with']) === $name) {
$className = $name;
}
} else {
list($plugin, $class) = pluginSplit($relation['with']);
if ($class === $name) {
$className = $relation['with'];
}
}
if ($className) {
$assocKey = $k;
$dynamic = !empty($relation['dynamicWith']);
break(2);
}
}
}
}
if (!$className) {
return false;
}
list($plugin, $className) = pluginSplit($className);
if (!ClassRegistry::isKeySet($className) && !empty($dynamic)) {
$this->{$className} = new AppModel(array(
'name' => $className,
'table' => $this->hasAndBelongsToMany[$assocKey]['joinTable'],
'ds' => $this->useDbConfig
));
} else {
$this->__constructLinkedModel($name, $className, $plugin);
}
if (!empty($assocKey)) {
$this->hasAndBelongsToMany[$assocKey]['joinTable'] = $this->{$name}->table;
if (count($this->{$name}->schema()) <= 2 && $this->{$name}->primaryKey !== false) {
$this->{$name}->primaryKey = $this->hasAndBelongsToMany[$assocKey]['foreignKey'];
}
}
return $this->{$name};
}
/**
* Returns the value of the requested variable if it can be set by __isset()
*
* @param string $name variable requested for it's value or reference
* @return mixed value of requested variable if it is set
*/
function __get($name) {
if ($name === 'displayField') {
return $this->displayField = $this->hasField(array('title', 'name', $this->primaryKey));
}
if (isset($this->{$name})) {
return $this->{$name};
}
}
/** /**
* Bind model associations on the fly. * Bind model associations on the fly.
* *
@ -532,6 +608,9 @@ class Model extends Object {
} }
$modelName = $assocName; $modelName = $assocName;
$this->{$assoc}[$assocName] = $value; $this->{$assoc}[$assocName] = $value;
if (property_exists($this, $assocName)) {
unset($this->{$assocName});
}
} }
} }
$this->__createLinks(); $this->__createLinks();
@ -601,21 +680,12 @@ class Model extends Object {
$this->{$type}[$assoc] = $value; $this->{$type}[$assoc] = $value;
if (strpos($assoc, '.') !== false) { if (strpos($assoc, '.') !== false) {
$value = $this->{$type}[$assoc]; list($plugin, $assoc) = pluginSplit($assoc);
unset($this->{$type}[$assoc]); $this->{$type}[$assoc] = array('className' => $plugin. '.' . $assoc);
list($plugin, $assoc) = pluginSplit($assoc, true);
$this->{$type}[$assoc] = $value;
} }
} }
$className = $assoc; $this->__generateAssociation($type, $assoc);
if (!empty($value['className'])) {
list($plugin, $className) = pluginSplit($value['className'], true);
$this->{$type}[$assoc]['className'] = $className;
} }
$this->__constructLinkedModel($assoc, $plugin . $className);
}
$this->__generateAssociation($type);
} }
} }
} }
@ -625,7 +695,7 @@ class Model extends Object {
* *
* @param string $assoc Association name * @param string $assoc Association name
* @param string $className Class name * @param string $className Class name
* @deprecated $this->$className use $this->$assoc instead. $assoc is the 'key' in the associations array; * @param string $plugin name of the plugin where $className is located
* examples: public $hasMany = array('Assoc' => array('className' => 'ModelName')); * examples: public $hasMany = array('Assoc' => array('className' => 'ModelName'));
* usage: $this->Assoc->modelMethods(); * usage: $this->Assoc->modelMethods();
* *
@ -634,16 +704,16 @@ class Model extends Object {
* @return void * @return void
* @access private * @access private
*/ */
function __constructLinkedModel($assoc, $className = null) { function __constructLinkedModel($assoc, $className = null, $plugin = null) {
if (empty($className)) { if (empty($className)) {
$className = $assoc; $className = $assoc;
} }
if (!isset($this->{$assoc}) || $this->{$assoc}->name !== $className) { if (!isset($this->{$assoc}) || $this->{$assoc}->name !== $className) {
$model = array('class' => $className, 'alias' => $assoc); $model = array('class' => $plugin . '.' . $className, 'alias' => $assoc);
$this->{$assoc} = ClassRegistry::init($model); $this->{$assoc} = ClassRegistry::init($model);
if (strpos($className, '.') !== false) { if ($plugin) {
ClassRegistry::addObject($className, $this->{$assoc}); ClassRegistry::addObject($plugin . '.' . $className, $this->{$assoc});
} }
if ($assoc) { if ($assoc) {
$this->tableToModel[$this->{$assoc}->table] = $assoc; $this->tableToModel[$this->{$assoc}->table] = $assoc;
@ -655,11 +725,11 @@ class Model extends Object {
* Build an array-based association from string. * Build an array-based association from string.
* *
* @param string $type 'belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany' * @param string $type 'belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany'
* @param string $assocKey
* @return void * @return void
* @access private * @access private
*/ */
function __generateAssociation($type) { function __generateAssociation($type, $assocKey) {
foreach ($this->{$type} as $assocKey => $assocData) {
$class = $assocKey; $class = $assocKey;
$dynamicWith = false; $dynamicWith = false;
@ -702,36 +772,11 @@ class Model extends Object {
} }
$this->{$type}[$assocKey][$key] = $data; $this->{$type}[$assocKey][$key] = $data;
} }
if ($dynamicWith) {
$this->{$type}[$assocKey]['dynamicWith'] = true;
} }
if (!empty($this->{$type}[$assocKey]['with'])) {
$joinClass = $this->{$type}[$assocKey]['with'];
if (is_array($joinClass)) {
$joinClass = key($joinClass);
}
$plugin = null;
if (strpos($joinClass, '.') !== false) {
list($plugin, $joinClass) = explode('.', $joinClass);
$plugin .= '.';
$this->{$type}[$assocKey]['with'] = $joinClass;
}
if (!ClassRegistry::isKeySet($joinClass) && $dynamicWith === true) {
$this->{$joinClass} = new AppModel(array(
'name' => $joinClass,
'table' => $this->{$type}[$assocKey]['joinTable'],
'ds' => $this->useDbConfig
));
} else {
$this->__constructLinkedModel($joinClass, $plugin . $joinClass);
$this->{$type}[$assocKey]['joinTable'] = $this->{$joinClass}->table;
}
if (count($this->{$joinClass}->schema()) <= 2 && $this->{$joinClass}->primaryKey !== false) {
$this->{$joinClass}->primaryKey = $this->{$type}[$assocKey]['foreignKey'];
}
}
} }
} }
@ -743,7 +788,7 @@ class Model extends Object {
*/ */
public function setSource($tableName) { public function setSource($tableName) {
$this->setDataSource($this->useDbConfig); $this->setDataSource($this->useDbConfig);
$db =& ConnectionManager::getDataSource($this->useDbConfig); $db = ConnectionManager::getDataSource($this->useDbConfig);
$db->cacheSources = ($this->cacheSources && $db->cacheSources); $db->cacheSources = ($this->cacheSources && $db->cacheSources);
if ($db->isInterfaceSupported('listSources')) { if ($db->isInterfaceSupported('listSources')) {
@ -758,7 +803,6 @@ class Model extends Object {
} }
$this->table = $this->useTable = $tableName; $this->table = $this->useTable = $tableName;
$this->tableToModel[$this->table] = $this->alias; $this->tableToModel[$this->table] = $this->alias;
$this->schema();
} }
/** /**
@ -841,7 +885,7 @@ class Model extends Object {
$dateFields = array('Y' => 'year', 'm' => 'month', 'd' => 'day', 'H' => 'hour', 'i' => 'min', 's' => 'sec'); $dateFields = array('Y' => 'year', 'm' => 'month', 'd' => 'day', 'H' => 'hour', 'i' => 'min', 's' => 'sec');
$timeFields = array('H' => 'hour', 'i' => 'min', 's' => 'sec'); $timeFields = array('H' => 'hour', 'i' => 'min', 's' => 'sec');
$db =& ConnectionManager::getDataSource($this->useDbConfig); $db = $this->getDataSource();
$format = $db->columns[$type]['format']; $format = $db->columns[$type]['format'];
$date = array(); $date = array();
@ -902,7 +946,7 @@ class Model extends Object {
*/ */
public function schema($field = false) { public function schema($field = false) {
if (!is_array($this->_schema) || $field === true) { if (!is_array($this->_schema) || $field === true) {
$db =& ConnectionManager::getDataSource($this->useDbConfig); $db = $this->getDataSource();
$db->cacheSources = ($this->cacheSources && $db->cacheSources); $db->cacheSources = ($this->cacheSources && $db->cacheSources);
if ($db->isInterfaceSupported('describe') && $this->useTable !== false) { if ($db->isInterfaceSupported('describe') && $this->useTable !== false) {
$this->_schema = $db->describe($this, $field); $this->_schema = $db->describe($this, $field);
@ -944,7 +988,7 @@ class Model extends Object {
* @return string Column type * @return string Column type
*/ */
public function getColumnType($column) { public function getColumnType($column) {
$db =& ConnectionManager::getDataSource($this->useDbConfig); $db = $this->getDataSource();
$cols = $this->schema(); $cols = $this->schema();
$model = null; $model = null;
@ -1231,7 +1275,7 @@ class Model extends Object {
return false; return false;
} }
$db =& ConnectionManager::getDataSource($this->useDbConfig); $db = $this->getDataSource();
foreach ($dateFields as $updateCol) { foreach ($dateFields as $updateCol) {
if ($this->hasField($updateCol) && !in_array($updateCol, $fields)) { if ($this->hasField($updateCol) && !in_array($updateCol, $fields)) {
@ -1300,7 +1344,7 @@ class Model extends Object {
if (!empty($this->id)) { if (!empty($this->id)) {
$success = (bool)$db->update($this, $fields, $values); $success = (bool)$db->update($this, $fields, $values);
} else { } else {
$fInfo = $this->_schema[$this->primaryKey]; $fInfo = $this->schema($this->primaryKey);
$isUUID = ($fInfo['length'] == 36 && $isUUID = ($fInfo['length'] == 36 &&
($fInfo['type'] === 'string' || $fInfo['type'] === 'binary') ($fInfo['type'] === 'string' || $fInfo['type'] === 'binary')
); );
@ -1361,10 +1405,11 @@ class Model extends Object {
if (isset($this->hasAndBelongsToMany[$assoc])) { if (isset($this->hasAndBelongsToMany[$assoc])) {
list($join) = $this->joinModel($this->hasAndBelongsToMany[$assoc]['with']); list($join) = $this->joinModel($this->hasAndBelongsToMany[$assoc]['with']);
$keyInfo = $this->{$join}->schema($this->{$join}->primaryKey);
$isUUID = !empty($this->{$join}->primaryKey) && ( $isUUID = !empty($this->{$join}->primaryKey) && (
$this->{$join}->_schema[$this->{$join}->primaryKey]['length'] == 36 && ( $keyInfo['length'] == 36 && (
$this->{$join}->_schema[$this->{$join}->primaryKey]['type'] === 'string' || $keyInfo['type'] === 'string' ||
$this->{$join}->_schema[$this->{$join}->primaryKey]['type'] === 'binary' $keyInfo['type'] === 'binary'
) )
); );
@ -1548,7 +1593,7 @@ class Model extends Object {
if (empty($data)) { if (empty($data)) {
$data = $this->data; $data = $this->data;
} }
$db =& ConnectionManager::getDataSource($this->useDbConfig); $db = $this->getDataSource();
$options = array_merge(array('validate' => 'first', 'atomic' => true), $options); $options = array_merge(array('validate' => 'first', 'atomic' => true), $options);
$this->validationErrors = $validationErrors = array(); $this->validationErrors = $validationErrors = array();
@ -1753,8 +1798,7 @@ class Model extends Object {
* @link http://book.cakephp.org/view/1031/Saving-Your-Data * @link http://book.cakephp.org/view/1031/Saving-Your-Data
*/ */
function updateAll($fields, $conditions = true) { function updateAll($fields, $conditions = true) {
$db =& ConnectionManager::getDataSource($this->useDbConfig); return $this->getDataSource()->update($this, $fields, null, $conditions);
return $db->update($this, $fields, null, $conditions);
} }
/** /**
@ -1773,7 +1817,7 @@ class Model extends Object {
$id = $this->id; $id = $this->id;
if ($this->exists() && $this->beforeDelete($cascade)) { if ($this->exists() && $this->beforeDelete($cascade)) {
$db =& ConnectionManager::getDataSource($this->useDbConfig); $db = $this->getDataSource();
$filters = $this->Behaviors->trigger($this, 'beforeDelete', array($cascade), array( $filters = $this->Behaviors->trigger($this, 'beforeDelete', array($cascade), array(
'break' => true, 'breakOn' => false 'break' => true, 'breakOn' => false
)); ));
@ -1820,7 +1864,7 @@ class Model extends Object {
foreach (array_merge($this->hasMany, $this->hasOne) as $assoc => $data) { foreach (array_merge($this->hasMany, $this->hasOne) as $assoc => $data) {
if ($data['dependent'] === true && $cascade === true) { if ($data['dependent'] === true && $cascade === true) {
$model =& $this->{$assoc}; $model = $this->{$assoc};
$conditions = array($model->escapeField($data['foreignKey']) => $id); $conditions = array($model->escapeField($data['foreignKey']) => $id);
if ($data['conditions']) { if ($data['conditions']) {
$conditions = array_merge((array)$data['conditions'], $conditions); $conditions = array_merge((array)$data['conditions'], $conditions);
@ -1883,7 +1927,7 @@ class Model extends Object {
if (empty($conditions)) { if (empty($conditions)) {
return false; return false;
} }
$db =& ConnectionManager::getDataSource($this->useDbConfig); $db = $this->getDataSource();
if (!$cascade && !$callbacks) { if (!$cascade && !$callbacks) {
return $db->delete($this, $conditions); return $db->delete($this, $conditions);
@ -2056,7 +2100,7 @@ class Model extends Object {
} }
} }
if (!$db =& ConnectionManager::getDataSource($this->useDbConfig)) { if (!$db = $this->getDataSource()) {
return false; return false;
} }
@ -2112,7 +2156,7 @@ class Model extends Object {
*/ */
function _findCount($state, $query, $results = array()) { function _findCount($state, $query, $results = array()) {
if ($state == 'before') { if ($state == 'before') {
$db =& ConnectionManager::getDataSource($this->useDbConfig); $db = $this->getDataSource();
if (empty($query['fields'])) { if (empty($query['fields'])) {
$query['fields'] = $db->calculate($this, 'count'); $query['fields'] = $db->calculate($this, 'count');
} elseif (is_string($query['fields']) && !preg_match('/count/i', $query['fields'])) { } elseif (is_string($query['fields']) && !preg_match('/count/i', $query['fields'])) {
@ -2330,7 +2374,7 @@ class Model extends Object {
foreach ($this->__associations as $type) { foreach ($this->__associations as $type) {
foreach ($this->{$type} as $key => $name) { foreach ($this->{$type} as $key => $name) {
if (!empty($this->{$key}->__backAssociation)) { if (property_exists($this, $key) && !empty($this->{$key}->__backAssociation)) {
$this->{$key}->resetAssociations(); $this->{$key}->resetAssociations();
} }
} }
@ -2391,7 +2435,7 @@ class Model extends Object {
*/ */
function query() { function query() {
$params = func_get_args(); $params = func_get_args();
$db =& ConnectionManager::getDataSource($this->useDbConfig); $db = $this->getDataSource();
return call_user_func_array(array(&$db, 'query'), $params); return call_user_func_array(array(&$db, 'query'), $params);
} }
@ -2653,7 +2697,7 @@ class Model extends Object {
if (empty($field)) { if (empty($field)) {
$field = $this->primaryKey; $field = $this->primaryKey;
} }
$db =& ConnectionManager::getDataSource($this->useDbConfig); $db = $this->getDataSource();
if (strpos($field, $db->name($alias) . '.') === 0) { if (strpos($field, $db->name($alias) . '.') === 0) {
return $field; return $field;
} }
@ -2725,8 +2769,7 @@ class Model extends Object {
* @return int Number of rows * @return int Number of rows
*/ */
public function getNumRows() { public function getNumRows() {
$db =& ConnectionManager::getDataSource($this->useDbConfig); return $this->getDataSource()->lastNumRows();
return $db->lastNumRows();
} }
/** /**
@ -2735,8 +2778,7 @@ class Model extends Object {
* @return int Number of rows * @return int Number of rows
*/ */
public function getAffectedRows() { public function getAffectedRows() {
$db =& ConnectionManager::getDataSource($this->useDbConfig); return $this->getDataSource()->lastAffected();
return $db->lastAffected();
} }
/** /**
@ -2751,9 +2793,9 @@ class Model extends Object {
if ($dataSource != null) { if ($dataSource != null) {
$this->useDbConfig = $dataSource; $this->useDbConfig = $dataSource;
} }
$db =& ConnectionManager::getDataSource($this->useDbConfig); $db = ConnectionManager::getDataSource($this->useDbConfig);
if (!empty($oldConfig) && isset($db->config['prefix'])) { if (!empty($oldConfig) && isset($db->config['prefix'])) {
$oldDb =& ConnectionManager::getDataSource($oldConfig); $oldDb = ConnectionManager::getDataSource($oldConfig);
if (!isset($this->tablePrefix) || (!isset($oldDb->config['prefix']) || $this->tablePrefix == $oldDb->config['prefix'])) { if (!isset($this->tablePrefix) || (!isset($oldDb->config['prefix']) || $this->tablePrefix == $oldDb->config['prefix'])) {
$this->tablePrefix = $db->config['prefix']; $this->tablePrefix = $db->config['prefix'];
@ -2774,8 +2816,12 @@ class Model extends Object {
* @return object A DataSource object * @return object A DataSource object
*/ */
public function &getDataSource() { public function &getDataSource() {
$db =& ConnectionManager::getDataSource($this->useDbConfig); static $configured = false;
return $db; if (!$configured && $this->useTable !== false) {
$configured = true;
$this->setSource($this->useTable);
}
return ConnectionManager::getDataSource($this->useDbConfig);
} }
/** /**
@ -2841,6 +2887,7 @@ class Model extends Object {
*/ */
public function joinModel($assoc, $keys = array()) { public function joinModel($assoc, $keys = array()) {
if (is_string($assoc)) { if (is_string($assoc)) {
list(, $assoc) = pluginSplit($assoc);
return array($assoc, array_keys($this->{$assoc}->schema())); return array($assoc, array_keys($this->{$assoc}->schema()));
} elseif (is_array($assoc)) { } elseif (is_array($assoc)) {
$with = key($assoc); $with = key($assoc);

View file

@ -20,6 +20,10 @@
* @license MIT License (http://www.opensource.org/licenses/mit-license.php) * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/ */
if (!class_exists('Router')) {
App::import('Core', 'Router');
}
/** /**
* Abstract base class for all other Helpers in CakePHP. * Abstract base class for all other Helpers in CakePHP.
* Provides common methods and features. * Provides common methods and features.

View file

@ -823,7 +823,7 @@ abstract class JsBaseEngineHelper extends AppHelper {
* @param array $options Array of options for the effect. * @param array $options Array of options for the effect.
* @return string completed string with effect. * @return string completed string with effect.
*/ */
abstract public function effect($name, $options); abstract public function effect($name, $options = array());
/** /**
* Make an XHR request * Make an XHR request
@ -913,7 +913,7 @@ abstract class JsBaseEngineHelper extends AppHelper {
* @param array $options Array of options for the sortable. See above. * @param array $options Array of options for the sortable. See above.
* @return string Completed sortable script. * @return string Completed sortable script.
*/ */
abstract public function sortable(); abstract public function sortable($options = array());
/** /**
* Create a slider UI widget. Comprised of a track and knob. * Create a slider UI widget. Comprised of a track and knob.
@ -935,7 +935,7 @@ abstract class JsBaseEngineHelper extends AppHelper {
* *
* @return string Completed slider script * @return string Completed slider script
*/ */
abstract public function slider(); abstract public function slider($options = array());
/** /**
* Serialize the form attached to $selector. * Serialize the form attached to $selector.
* Pass `true` for $isForm if the current selection is a form element. * Pass `true` for $isForm if the current selection is a form element.
@ -950,7 +950,7 @@ abstract class JsBaseEngineHelper extends AppHelper {
* @param array $options options for serialization generation. * @param array $options options for serialization generation.
* @return string completed form serialization script * @return string completed form serialization script
*/ */
abstract public function serializeForm(); abstract public function serializeForm($options = array());
/** /**
* Parse an options assoc array into an Javascript object literal. * Parse an options assoc array into an Javascript object literal.

View file

@ -19,6 +19,7 @@
* @license MIT License (http://www.opensource.org/licenses/mit-license.php) * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/ */
App::import('Shell', 'Shell', false); App::import('Shell', 'Shell', false);
App::import('Core', 'Controller');
if (!defined('DISABLE_AUTO_DISPATCH')) { if (!defined('DISABLE_AUTO_DISPATCH')) {
define('DISABLE_AUTO_DISPATCH', true); define('DISABLE_AUTO_DISPATCH', true);

View file

@ -283,7 +283,7 @@ class SchemaShellTest extends CakeTestCase {
$this->Shell->Schema->expects($this->at(0))->method('write')->will($this->returnValue(true)); $this->Shell->Schema->expects($this->at(0))->method('write')->will($this->returnValue(true));
$this->Shell->Schema->expects($this->at(1))->method('read'); $this->Shell->Schema->expects($this->at(1))->method('read');
$this->Shell->Schema->expects($this->at(1))->method('write')->with(array('schema data', 'file' => 'schema_1.php')); $this->Shell->Schema->expects($this->at(1))->method('write')->with(array('schema data', 'file' => 'schema_0.php'));
$this->Shell->generate(); $this->Shell->generate();
} }
@ -406,7 +406,7 @@ class SchemaShellTest extends CakeTestCase {
$this->Shell->expects($this->any())->method('in')->will($this->returnValue('y')); $this->Shell->expects($this->any())->method('in')->will($this->returnValue('y'));
$this->Shell->create(); $this->Shell->create();
$db =& ConnectionManager::getDataSource('test_suite'); $db =& ConnectionManager::getDataSource('test');
$sources = $db->listSources(); $sources = $db->listSources();
$this->assertTrue(in_array($db->config['prefix'] . 'acos', $sources)); $this->assertTrue(in_array($db->config['prefix'] . 'acos', $sources));
$this->assertFalse(in_array($db->config['prefix'] . 'aros', $sources)); $this->assertFalse(in_array($db->config['prefix'] . 'aros', $sources));

View file

@ -39,18 +39,18 @@ require_once CAKE . 'console' . DS . 'libs' . DS . 'tasks' . DS . 'template.php
require_once CAKE . 'console' . DS . 'libs' . DS . 'tasks' . DS . 'test.php'; require_once CAKE . 'console' . DS . 'libs' . DS . 'tasks' . DS . 'test.php';
$imported = App::import('Model', 'Article'); $imported = App::import('Model', 'BakeArticle');
$imported = $imported || App::import('Model', 'Comment'); $imported = $imported || App::import('Model', 'BakeComment');
$imported = $imported || App::import('Model', 'Tag'); $imported = $imported || App::import('Model', 'BakeTag');
if (!$imported) { if (!$imported) {
define('ARTICLE_MODEL_CREATED', true); define('ARTICLE_MODEL_CREATED', true);
App::import('Core', 'Model'); App::import('Core', 'Model');
class Article extends Model { class BakeArticle extends Model {
public $name = 'Article'; public $name = 'BakeArticle';
public $hasMany = array('Comment'); public $hasMany = array('BakeComment');
public $hasAndBelongsToMany = array('Tag'); public $hasAndBelongsToMany = array('BakeTag');
} }
} }
@ -69,7 +69,7 @@ class ControllerTaskTest extends CakeTestCase {
* @var array * @var array
* @access public * @access public
*/ */
public $fixtures = array('core.article', 'core.comment', 'core.articles_tag', 'core.tag'); public $fixtures = array('core.bake_article', 'core.bake_articles_bake_tag', 'core.bake_comment', 'core.bake_tag');
/** /**
* startTest method * startTest method
@ -116,21 +116,26 @@ class ControllerTaskTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testListAll() { public function testListAll() {
$count = count($this->Task->listAll('test_suite'));
if ($count != count($this->fixtures)) {
$this->markTestSkipped('Additional tables detected.');
}
$this->Task->connection = 'test_suite'; $this->Task->connection = 'test_suite';
$this->Task->interactive = true; $this->Task->interactive = true;
$this->Task->expects($this->at(1))->method('out')->with('1. Articles'); $this->Task->expects($this->at(1))->method('out')->with('1. BakeArticles');
$this->Task->expects($this->at(2))->method('out')->with('2. ArticlesTags'); $this->Task->expects($this->at(2))->method('out')->with('2. BakeArticlesBakeTags');
$this->Task->expects($this->at(3))->method('out')->with('3. Comments'); $this->Task->expects($this->at(3))->method('out')->with('3. BakeComments');
$this->Task->expects($this->at(4))->method('out')->with('4. Tags'); $this->Task->expects($this->at(4))->method('out')->with('4. BakeTags');
$expected = array('Articles', 'ArticlesTags', 'Comments', 'Tags'); $expected = array('BakeArticles', 'BakeArticlesBakeTags', 'BakeComments', 'BakeTags');
$result = $this->Task->listAll('test_suite'); $result = $this->Task->listAll('test_suite');
$this->assertEqual($result, $expected); $this->assertEqual($result, $expected);
$this->Task->interactive = false; $this->Task->interactive = false;
$result = $this->Task->listAll(); $result = $this->Task->listAll();
$expected = array('articles', 'articles_tags', 'comments', 'tags'); $expected = array('bake_articles', 'bake_articles_bake_tags', 'bake_comments', 'bake_tags');
$this->assertEqual($result, $expected); $this->assertEqual($result, $expected);
} }
@ -140,15 +145,20 @@ class ControllerTaskTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testGetNameValidIndex() { public function testGetNameValidIndex() {
$count = count($this->Task->listAll('test_suite'));
if ($count != count($this->fixtures)) {
$this->markTestSkipped('Additional tables detected.');
}
$this->Task->interactive = true; $this->Task->interactive = true;
$this->Task->expects($this->at(5))->method('in')->will($this->returnValue(3)); $this->Task->expects($this->at(5))->method('in')->will($this->returnValue(3));
$this->Task->expects($this->at(7))->method('in')->will($this->returnValue(1));
$result = $this->Task->getName('test_suite'); $result = $this->Task->getName('test_suite');
$expected = 'Comments'; $expected = 'BakeComments';
$this->assertEqual($result, $expected); $this->assertEqual($result, $expected);
$this->Task->expects($this->at(7))->method('in')->will($this->returnValue(1));
$result = $this->Task->getName('test_suite'); $result = $this->Task->getName('test_suite');
$expected = 'Articles'; $expected = 'BakeArticles';
$this->assertEqual($result, $expected); $this->assertEqual($result, $expected);
} }
@ -159,8 +169,9 @@ class ControllerTaskTest extends CakeTestCase {
*/ */
function testGetNameInvalidIndex() { function testGetNameInvalidIndex() {
$this->Task->interactive = true; $this->Task->interactive = true;
$this->Task->expects($this->at(5))->method('in')->will($this->returnValue(10)); $this->Task->expects($this->any())->method('in')
$this->Task->expects($this->at(7))->method('in')->will($this->returnValue('q')); ->will($this->onConsecutiveCalls(50, 'q'));
$this->Task->expects($this->once())->method('err'); $this->Task->expects($this->once())->method('err');
$this->Task->expects($this->once())->method('_stop'); $this->Task->expects($this->once())->method('_stop');
@ -272,22 +283,22 @@ class ControllerTaskTest extends CakeTestCase {
$this->Task->expects($this->any())->method('createFile')->will($this->returnValue(true)); $this->Task->expects($this->any())->method('createFile')->will($this->returnValue(true));
$result = $this->Task->bake('Articles', '--actions--', $helpers, $components); $result = $this->Task->bake('Articles', '--actions--', $helpers, $components);
$this->assertPattern('/class ArticlesController extends AppController/', $result); $this->assertContains('class ArticlesController extends AppController', $result);
$this->assertPattern('/\$components \= array\(\'Acl\', \'Auth\'\)/', $result); $this->assertContains("\$components = array('Acl', 'Auth')", $result);
$this->assertPattern('/\$helpers \= array\(\'Ajax\', \'Time\'\)/', $result); $this->assertContains("\$helpers = array('Ajax', 'Time')", $result);
$this->assertPattern('/\-\-actions\-\-/', $result); $this->assertContains("--actions--", $result);
$result = $this->Task->bake('Articles', 'scaffold', $helpers, $components); $result = $this->Task->bake('Articles', 'scaffold', $helpers, $components);
$this->assertPattern('/class ArticlesController extends AppController/', $result); $this->assertContains("class ArticlesController extends AppController", $result);
$this->assertPattern('/public \$scaffold/', $result); $this->assertContains("public \$scaffold", $result);
$this->assertNoPattern('/helpers/', $result); $this->assertNotContains('helpers', $result);
$this->assertNoPattern('/components/', $result); $this->assertNotContains('components', $result);
$result = $this->Task->bake('Articles', '--actions--', array(), array()); $result = $this->Task->bake('Articles', '--actions--', array(), array());
$this->assertPattern('/class ArticlesController extends AppController/', $result); $this->assertContains('class ArticlesController extends AppController', $result);
$this->assertNoPattern('/components/', $result); $this->assertNotContains('components', $result);
$this->assertNoPattern('/helpers/', $result); $this->assertNotContains('helpers', $result);
$this->assertPattern('/\-\-actions\-\-/', $result); $this->assertContains('--actions--', $result);
} }
/** /**
@ -330,35 +341,35 @@ class ControllerTaskTest extends CakeTestCase {
if ($skip) { if ($skip) {
return; return;
} }
$result = $this->Task->bakeActions('Articles', null, true); $result = $this->Task->bakeActions('BakeArticles', null, true);
$this->assertTrue(strpos($result, 'function index() {') !== false); $this->assertContains('function index() {', $result);
$this->assertTrue(strpos($result, '$this->Article->recursive = 0;') !== false); $this->assertContains('$this->BakeArticle->recursive = 0;', $result);
$this->assertTrue(strpos($result, "\$this->set('articles', \$this->paginate());") !== false); $this->assertContains("\$this->set('bakeArticles', \$this->paginate());", $result);
$this->assertTrue(strpos($result, 'function view($id = null)') !== false); $this->assertContains('function view($id = null)', $result);
$this->assertTrue(strpos($result, "\$this->Session->setFlash(__('Invalid article'));") !== false); $this->assertContains("\$this->Session->setFlash(__('Invalid bake article'));", $result);
$this->assertTrue(strpos($result, "\$this->set('article', \$this->Article->read(null, \$id)") !== false); $this->assertContains("\$this->set('bakeArticle', \$this->BakeArticle->read(null, \$id)", $result);
$this->assertTrue(strpos($result, 'function add()') !== false); $this->assertContains('function add()', $result);
$this->assertTrue(strpos($result, 'if (!empty($this->data))') !== false); $this->assertContains('if (!empty($this->data))', $result);
$this->assertTrue(strpos($result, 'if ($this->Article->save($this->data))') !== false); $this->assertContains('if ($this->BakeArticle->save($this->data))', $result);
$this->assertTrue(strpos($result, "\$this->Session->setFlash(__('The article has been saved'));") !== false); $this->assertContains("\$this->Session->setFlash(__('The bake article has been saved'));", $result);
$this->assertTrue(strpos($result, 'function edit($id = null)') !== false); $this->assertContains('function edit($id = null)', $result);
$this->assertTrue(strpos($result, "\$this->Session->setFlash(__('The article could not be saved. Please, try again.'));") !== false); $this->assertContains("\$this->Session->setFlash(__('The bake article could not be saved. Please, try again.'));", $result);
$this->assertTrue(strpos($result, 'function delete($id = null)') !== false); $this->assertContains('function delete($id = null)', $result);
$this->assertTrue(strpos($result, 'if ($this->Article->delete($id))') !== false); $this->assertContains('if ($this->BakeArticle->delete($id))', $result);
$this->assertTrue(strpos($result, "\$this->Session->setFlash(__('Article deleted'));") !== false); $this->assertContains("\$this->Session->setFlash(__('Bake article deleted'));", $result);
$result = $this->Task->bakeActions('Articles', 'admin_', true); $result = $this->Task->bakeActions('BakeArticles', 'admin_', true);
$this->assertTrue(strpos($result, 'function admin_index() {') !== false); $this->assertContains('function admin_index() {', $result);
$this->assertTrue(strpos($result, 'function admin_add()') !== false); $this->assertContains('function admin_add()', $result);
$this->assertTrue(strpos($result, 'function admin_view($id = null)') !== false); $this->assertContains('function admin_view($id = null)', $result);
$this->assertTrue(strpos($result, 'function admin_edit($id = null)') !== false); $this->assertContains('function admin_edit($id = null)', $result);
$this->assertTrue(strpos($result, 'function admin_delete($id = null)') !== false); $this->assertContains('function admin_delete($id = null)', $result);
} }
/** /**
@ -372,29 +383,29 @@ class ControllerTaskTest extends CakeTestCase {
if ($skip) { if ($skip) {
return; return;
} }
$result = $this->Task->bakeActions('Articles', null, false); $result = $this->Task->bakeActions('BakeArticles', null, false);
$this->assertTrue(strpos($result, 'function index() {') !== false); $this->assertContains('function index() {', $result);
$this->assertTrue(strpos($result, '$this->Article->recursive = 0;') !== false); $this->assertContains('$this->BakeArticle->recursive = 0;', $result);
$this->assertTrue(strpos($result, "\$this->set('articles', \$this->paginate());") !== false); $this->assertContains("\$this->set('bakeArticles', \$this->paginate());", $result);
$this->assertTrue(strpos($result, 'function view($id = null)') !== false); $this->assertContains('function view($id = null)', $result);
$this->assertTrue(strpos($result, "\$this->flash(__('Invalid article'), array('action' => 'index'))") !== false); $this->assertContains("\$this->flash(__('Invalid bake article'), array('action' => 'index'))", $result);
$this->assertTrue(strpos($result, "\$this->set('article', \$this->Article->read(null, \$id)") !== false); $this->assertContains("\$this->set('bakeArticle', \$this->BakeArticle->read(null, \$id)", $result);
$this->assertTrue(strpos($result, 'function add()') !== false); $this->assertContains('function add()', $result);
$this->assertTrue(strpos($result, 'if (!empty($this->data))') !== false); $this->assertContains('if (!empty($this->data))', $result);
$this->assertTrue(strpos($result, 'if ($this->Article->save($this->data))') !== false); $this->assertContains('if ($this->BakeArticle->save($this->data))', $result);
$this->assertTrue(strpos($result, "\$this->flash(__('The article has been saved.'), array('action' => 'index'))") !== false); $this->assertContains("\$this->flash(__('The bake article has been saved.'), array('action' => 'index'))", $result);
$this->assertTrue(strpos($result, 'function edit($id = null)') !== false); $this->assertContains('function edit($id = null)', $result);
$this->assertTrue(strpos($result, "\$this->Article->Tag->find('list')") !== false); $this->assertContains("\$this->BakeArticle->BakeTag->find('list')", $result);
$this->assertTrue(strpos($result, "\$this->set(compact('tags'))") !== false); $this->assertContains("\$this->set(compact('bakeTags'))", $result);
$this->assertTrue(strpos($result, 'function delete($id = null)') !== false); $this->assertContains('function delete($id = null)', $result);
$this->assertTrue(strpos($result, 'if ($this->Article->delete($id))') !== false); $this->assertContains('if ($this->BakeArticle->delete($id))', $result);
$this->assertTrue(strpos($result, "\$this->flash(__('Article deleted'), array('action' => 'index'))") !== false); $this->assertContains("\$this->flash(__('Bake article deleted'), array('action' => 'index'))", $result);
} }
/** /**
@ -407,8 +418,8 @@ class ControllerTaskTest extends CakeTestCase {
$this->Task->connection = 'test_suite'; $this->Task->connection = 'test_suite';
$this->Task->interactive = false; $this->Task->interactive = false;
$this->Task->Test->expects($this->once())->method('bake')->with('Controller', 'Articles'); $this->Task->Test->expects($this->once())->method('bake')->with('Controller', 'BakeArticles');
$this->Task->bakeTest('Articles'); $this->Task->bakeTest('BakeArticles');
$this->assertEqual($this->Task->plugin, $this->Task->Test->plugin); $this->assertEqual($this->Task->plugin, $this->Task->Test->plugin);
$this->assertEqual($this->Task->connection, $this->Task->Test->connection); $this->assertEqual($this->Task->connection, $this->Task->Test->connection);
@ -421,6 +432,11 @@ class ControllerTaskTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testInteractive() { public function testInteractive() {
$count = count($this->Task->listAll('test_suite'));
if ($count != count($this->fixtures)) {
$this->markTestSkipped('Additional tables detected.');
}
$this->Task->connection = 'test_suite'; $this->Task->connection = 'test_suite';
$this->Task->path = '/my/path/'; $this->Task->path = '/my/path/';
@ -437,10 +453,10 @@ class ControllerTaskTest extends CakeTestCase {
'y' // looks good? 'y' // looks good?
)); ));
$filename = '/my/path/articles_controller.php'; $filename = '/my/path/bake_articles_controller.php';
$this->Task->expects($this->once())->method('createFile')->with( $this->Task->expects($this->once())->method('createFile')->with(
$filename, $filename,
new PHPUnit_Framework_Constraint_PCREMatch('/class ArticlesController/') new PHPUnit_Framework_Constraint_PCREMatch('/class BakeArticlesController/')
); );
$this->Task->execute(); $this->Task->execute();
} }
@ -449,9 +465,13 @@ class ControllerTaskTest extends CakeTestCase {
* test Interactive mode. * test Interactive mode.
* *
* @return void * @return void
* @access public
*/ */
function testInteractiveAdminMethodsNotInteractive() { function testInteractiveAdminMethodsNotInteractive() {
$count = count($this->Task->listAll('test_suite'));
if ($count != count($this->fixtures)) {
$this->markTestSkipped('Additional tables detected.');
}
$this->Task->connection = 'test_suite'; $this->Task->connection = 'test_suite';
$this->Task->interactive = true; $this->Task->interactive = true;
$this->Task->path = '/my/path/'; $this->Task->path = '/my/path/';
@ -473,10 +493,10 @@ class ControllerTaskTest extends CakeTestCase {
->method('getPrefix') ->method('getPrefix')
->will($this->returnValue('admin_')); ->will($this->returnValue('admin_'));
$filename = '/my/path/articles_controller.php'; $filename = '/my/path/bake_articles_controller.php';
$this->Task->expects($this->once())->method('createFile')->with( $this->Task->expects($this->once())->method('createFile')->with(
$filename, $filename,
new PHPUnit_Framework_Constraint_PCREMatch('/class ArticlesController/') new PHPUnit_Framework_Constraint_PCREMatch('/class BakeArticlesController/')
)->will($this->returnValue(true)); )->will($this->returnValue(true));
$result = $this->Task->execute(); $result = $this->Task->execute();
@ -501,10 +521,10 @@ class ControllerTaskTest extends CakeTestCase {
$this->Task->expects($this->any())->method('_checkUnitTest')->will($this->returnValue(true)); $this->Task->expects($this->any())->method('_checkUnitTest')->will($this->returnValue(true));
$this->Task->Test->expects($this->once())->method('bake'); $this->Task->Test->expects($this->once())->method('bake');
$filename = '/my/path/articles_controller.php'; $filename = '/my/path/bake_articles_controller.php';
$this->Task->expects($this->once())->method('createFile')->with( $this->Task->expects($this->once())->method('createFile')->with(
$filename, $filename,
new PHPUnit_Framework_Constraint_PCREMatch('/class ArticlesController/') new PHPUnit_Framework_Constraint_PCREMatch('/class BakeArticlesController/')
)->will($this->returnValue(true)); )->will($this->returnValue(true));
$this->Task->execute(); $this->Task->execute();
@ -523,9 +543,9 @@ class ControllerTaskTest extends CakeTestCase {
} }
$this->Task->connection = 'test_suite'; $this->Task->connection = 'test_suite';
$this->Task->path = '/my/path/'; $this->Task->path = '/my/path/';
$this->Task->args = array('Articles'); $this->Task->args = array('BakeArticles');
$filename = '/my/path/articles_controller.php'; $filename = '/my/path/bake_articles_controller.php';
$this->Task->expects($this->once())->method('createFile')->with( $this->Task->expects($this->once())->method('createFile')->with(
$filename, $filename,
new PHPUnit_Framework_Constraint_PCREMatch('/\$scaffold/') new PHPUnit_Framework_Constraint_PCREMatch('/\$scaffold/')
@ -541,7 +561,7 @@ class ControllerTaskTest extends CakeTestCase {
*/ */
static function nameVariations() { static function nameVariations() {
return array( return array(
array('Articles'), array('Article'), array('article'), array('articles') array('BakeArticles'), array('BakeArticle'), array('bake_article'), array('bake_articles')
); );
} }
@ -561,7 +581,7 @@ class ControllerTaskTest extends CakeTestCase {
$this->Task->path = '/my/path/'; $this->Task->path = '/my/path/';
$this->Task->args = array($name); $this->Task->args = array($name);
$filename = '/my/path/articles_controller.php'; $filename = '/my/path/bake_articles_controller.php';
$this->Task->expects($this->once())->method('createFile')->with( $this->Task->expects($this->once())->method('createFile')->with(
$filename, new PHPUnit_Framework_Constraint_PCREMatch('/\$scaffold/') $filename, new PHPUnit_Framework_Constraint_PCREMatch('/\$scaffold/')
); );
@ -581,9 +601,9 @@ class ControllerTaskTest extends CakeTestCase {
} }
$this->Task->connection = 'test_suite'; $this->Task->connection = 'test_suite';
$this->Task->path = '/my/path/'; $this->Task->path = '/my/path/';
$this->Task->args = array('Articles', 'public'); $this->Task->args = array('BakeArticles', 'public');
$filename = '/my/path/articles_controller.php'; $filename = '/my/path/bake_articles_controller.php';
$expected = new PHPUnit_Framework_Constraint_Not(new PHPUnit_Framework_Constraint_PCREMatch('/\$scaffold/')); $expected = new PHPUnit_Framework_Constraint_Not(new PHPUnit_Framework_Constraint_PCREMatch('/\$scaffold/'));
$this->Task->expects($this->once())->method('createFile')->with( $this->Task->expects($this->once())->method('createFile')->with(
$filename, $expected $filename, $expected
@ -605,9 +625,9 @@ class ControllerTaskTest extends CakeTestCase {
$this->Task->Project->expects($this->any())->method('getPrefix')->will($this->returnValue('admin_')); $this->Task->Project->expects($this->any())->method('getPrefix')->will($this->returnValue('admin_'));
$this->Task->connection = 'test_suite'; $this->Task->connection = 'test_suite';
$this->Task->path = '/my/path/'; $this->Task->path = '/my/path/';
$this->Task->args = array('Articles', 'public', 'admin'); $this->Task->args = array('BakeArticles', 'public', 'admin');
$filename = '/my/path/articles_controller.php'; $filename = '/my/path/bake_articles_controller.php';
$this->Task->expects($this->once())->method('createFile')->with( $this->Task->expects($this->once())->method('createFile')->with(
$filename, new PHPUnit_Framework_Constraint_PCREMatch('/admin_index/') $filename, new PHPUnit_Framework_Constraint_PCREMatch('/admin_index/')
); );
@ -628,9 +648,9 @@ class ControllerTaskTest extends CakeTestCase {
$this->Task->Project->expects($this->any())->method('getPrefix')->will($this->returnValue('admin_')); $this->Task->Project->expects($this->any())->method('getPrefix')->will($this->returnValue('admin_'));
$this->Task->connection = 'test_suite'; $this->Task->connection = 'test_suite';
$this->Task->path = '/my/path/'; $this->Task->path = '/my/path/';
$this->Task->args = array('Articles', 'admin'); $this->Task->args = array('BakeArticles', 'admin');
$filename = '/my/path/articles_controller.php'; $filename = '/my/path/bake_articles_controller.php';
$this->Task->expects($this->once())->method('createFile')->with( $this->Task->expects($this->once())->method('createFile')->with(
$filename, new PHPUnit_Framework_Constraint_PCREMatch('/admin_index/') $filename, new PHPUnit_Framework_Constraint_PCREMatch('/admin_index/')
); );

View file

@ -149,9 +149,6 @@ class ExtractTaskTest extends CakeTestCase {
$Folder = new Folder($path); $Folder = new Folder($path);
$Folder->delete(); $Folder->delete();
} }
function getTests() {
return array('start', 'startCase', 'testExtractMultiplePaths', 'endCase', 'end');
}
/** /**
* test extract can read more than one path. * test extract can read more than one path.
@ -169,8 +166,8 @@ class ExtractTaskTest extends CakeTestCase {
TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'views' . DS . 'posts'; TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'views' . DS . 'posts';
$this->Task->params['output'] = $path . DS; $this->Task->params['output'] = $path . DS;
$this->Task->Dispatch->expectNever('stderr'); $this->Task->Dispatch->expects($this->never())->method('stderr');
$this->Task->Dispatch->expectNever('_stop'); $this->Task->Dispatch->expects($this->never())->method('_stop');
$this->Task->execute(); $this->Task->execute();
$result = file_get_contents($path . DS . 'default.pot'); $result = file_get_contents($path . DS . 'default.pot');

View file

@ -341,10 +341,10 @@ class FixtureTaskTest extends CakeTestCase {
$filename = '/my/path/article_fixture.php'; $filename = '/my/path/article_fixture.php';
$this->Task->expects($this->at(0))->method('createFile') $this->Task->expects($this->at(0))->method('createFile')
->with($filename, new PHPUnit_Framework_Constraint_PCREMatch('/Article/')); ->with($filename, new PHPUnit_Framework_Constraint_PCREMatch('/ArticleFixture/'));
$this->Task->expects($this->at(1))->method('createFile') $this->Task->expects($this->at(1))->method('createFile')
->with($filename, new PHPUnit_Framework_Constraint_PCREMatch('/\<\?php(.*)\?\>/ms')); ->with($filename, new PHPUnit_Framework_Constraint_PCREMatch('/\<\?php/ms'));
$result = $this->Task->generateFixtureFile('Article', array()); $result = $this->Task->generateFixtureFile('Article', array());

View file

@ -112,6 +112,10 @@ class ModelTaskTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testListAll() { public function testListAll() {
$count = count($this->Task->listAll('test_suite'));
if ($count != count($this->fixtures)) {
$this->markTestSkipped('Additional tables detected.');
}
$this->_useMockedOut(); $this->_useMockedOut();
$this->Task->expects($this->at(1))->method('out')->with('1. Article'); $this->Task->expects($this->at(1))->method('out')->with('1. Article');
@ -153,8 +157,12 @@ class ModelTaskTest extends CakeTestCase {
* @return void * @return void
*/ */
function testGetNameValidOption() { function testGetNameValidOption() {
$this->Task->expects($this->at(0))->method('in')->will($this->returnValue(1)); $count = count($this->Task->listAll('test_suite'));
$this->Task->expects($this->at(1))->method('in')->will($this->returnValue(4)); if ($count != count($this->fixtures)) {
$this->markTestSkipped('Additional tables detected.');
}
$this->Task->expects($this->any())->method('in')->will($this->onConsecutiveCalls(1, 4));
$result = $this->Task->getName('test_suite'); $result = $this->Task->getName('test_suite');
$expected = 'Article'; $expected = 'Article';
@ -171,8 +179,7 @@ class ModelTaskTest extends CakeTestCase {
* @return void * @return void
*/ */
function testGetNameWithOutOfBoundsOption() { function testGetNameWithOutOfBoundsOption() {
$this->Task->expects($this->at(0))->method('in')->will($this->returnValue(10)); $this->Task->expects($this->any())->method('in')->will($this->onConsecutiveCalls(10, 1));
$this->Task->expects($this->at(2))->method('in')->will($this->returnValue(1));
$this->Task->expects($this->once())->method('err'); $this->Task->expects($this->once())->method('err');
$result = $this->Task->getName('test_suite'); $result = $this->Task->getName('test_suite');
@ -196,8 +203,7 @@ class ModelTaskTest extends CakeTestCase {
* @return void * @return void
*/ */
function testGetTableNameCustom() { function testGetTableNameCustom() {
$this->Task->expects($this->at(0))->method('in')->will($this->returnValue('n')); $this->Task->expects($this->any())->method('in')->will($this->onConsecutiveCalls('n', 'my_table'));
$this->Task->expects($this->at(1))->method('in')->will($this->returnValue('my_table'));
$result = $this->Task->getTable('Article', 'test_suite'); $result = $this->Task->getTable('Article', 'test_suite');
$expected = 'my_table'; $expected = 'my_table';
$this->assertEqual($result, $expected); $this->assertEqual($result, $expected);
@ -287,8 +293,8 @@ class ModelTaskTest extends CakeTestCase {
function testInteractiveFieldValidationWithRegexp() { function testInteractiveFieldValidationWithRegexp() {
$this->Task->initValidations(); $this->Task->initValidations();
$this->Task->interactive = true; $this->Task->interactive = true;
$this->Task->expects($this->at(0))->method('in')->will($this->returnValue('/^[a-z]{0,9}$/')); $this->Task->expects($this->any())->method('in')
$this->Task->expects($this->at(1))->method('in')->will($this->returnValue('n')); ->will($this->onConsecutiveCalls('/^[a-z]{0,9}$/', 'n'));
$result = $this->Task->fieldValidation('text', array('type' => 'string', 'length' => 10, 'null' => false)); $result = $this->Task->fieldValidation('text', array('type' => 'string', 'length' => 10, 'null' => false));
$expected = array('a_z_0_9' => '/^[a-z]{0,9}$/'); $expected = array('a_z_0_9' => '/^[a-z]{0,9}$/');
@ -402,8 +408,9 @@ class ModelTaskTest extends CakeTestCase {
'id' => array(), 'tagname' => array(), 'body' => array(), 'id' => array(), 'tagname' => array(), 'body' => array(),
'created' => array(), 'modified' => array() 'created' => array(), 'modified' => array()
); );
$this->Task->expects($this->at(0))->method('in')->will($this->returnValue('y')); $this->Task->expects($this->any())->method('in')
$this->Task->expects($this->at(1))->method('in')->will($this->returnValue(2)); ->will($this->onConsecutiveCalls('y', 2));
$result = $this->Task->findDisplayField($fields); $result = $this->Task->findDisplayField($fields);
$this->assertEqual($result, 'tagname'); $this->assertEqual($result, 'tagname');
} }
@ -501,6 +508,11 @@ class ModelTaskTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testHasAndBelongsToManyGeneration() { public function testHasAndBelongsToManyGeneration() {
$count = count($this->Task->listAll('test_suite'));
if ($count != count($this->fixtures)) {
$this->markTestSkipped('Additional tables detected.');
}
$model = new Model(array('ds' => 'test_suite', 'name' => 'Article')); $model = new Model(array('ds' => 'test_suite', 'name' => 'Article'));
$this->Task->connection = 'test_suite'; $this->Task->connection = 'test_suite';
$this->Task->listAll(); $this->Task->listAll();
@ -831,6 +843,11 @@ STRINGEND;
* @return void * @return void
*/ */
public function testExecuteIntoAll() { public function testExecuteIntoAll() {
$count = count($this->Task->listAll('test_suite'));
if ($count != count($this->fixtures)) {
$this->markTestSkipped('Additional tables detected.');
}
$this->Task->connection = 'test_suite'; $this->Task->connection = 'test_suite';
$this->Task->path = '/my/path/'; $this->Task->path = '/my/path/';
$this->Task->args = array('all'); $this->Task->args = array('all');
@ -871,6 +888,11 @@ STRINGEND;
* @return void * @return void
*/ */
function testSkipTablesAndAll() { function testSkipTablesAndAll() {
$count = count($this->Task->listAll('test_suite'));
if ($count != count($this->fixtures)) {
$this->markTestSkipped('Additional tables detected.');
}
$this->Task->connection = 'test_suite'; $this->Task->connection = 'test_suite';
$this->Task->path = '/my/path/'; $this->Task->path = '/my/path/';
$this->Task->args = array('all'); $this->Task->args = array('all');
@ -905,6 +927,11 @@ STRINGEND;
* @return void * @return void
*/ */
public function testExecuteIntoInteractive() { public function testExecuteIntoInteractive() {
$count = count($this->Task->listAll('test_suite'));
if ($count != count($this->fixtures)) {
$this->markTestSkipped('Additional tables detected.');
}
$this->Task->connection = 'test_suite'; $this->Task->connection = 'test_suite';
$this->Task->path = '/my/path/'; $this->Task->path = '/my/path/';
$this->Task->interactive = true; $this->Task->interactive = true;
@ -948,8 +975,9 @@ STRINGEND;
$this->Task->expects($this->once())->method('_stop'); $this->Task->expects($this->once())->method('_stop');
$this->Task->expects($this->once())->method('err'); $this->Task->expects($this->once())->method('err');
$this->Task->expects($this->at(0))->method('in')->will($this->returnValue('Foobar')); $this->Task->expects($this->any())->method('in')
$this->Task->expects($this->at(1))->method('in')->will($this->returnValue('y')); ->will($this->onConsecutiveCalls('Foobar', 'y'));
$this->Task->execute(); $this->Task->execute();
} }
} }

View file

@ -0,0 +1,119 @@
<?php
/**
* TestSuiteShell test case
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package cake
* @subpackage cake.cake.tests.libs
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::import('Shell', 'Shell', false);
if (!defined('DISABLE_AUTO_DISPATCH')) {
define('DISABLE_AUTO_DISPATCH', true);
}
if (!class_exists('ShellDispatcher')) {
ob_start();
$argv = false;
require CAKE . 'console' . DS . 'cake.php';
ob_end_clean();
}
require_once CAKE . 'console' . DS . 'libs' . DS . 'testsuite.php';
class TestSuiteShellTest extends CakeTestCase {
/**
* setUp test case
*
* @return void
*/
public function setUp() {
$this->Dispatcher = $this->getMock(
'ShellDispatcher',
array('getInput', 'stdout', 'stderr', '_stop', '_initEnvironment')
);
$this->Shell = $this->getMock(
'TestSuiteShell',
array('in', 'out', 'hr', 'help', 'error', 'err', '_stop', 'initialize', 'run'),
array(&$this->Dispatcher)
);
$this->Shell->Dispatch->shellPaths = App::path('shells');
}
/**
* tearDown method
*
* @return void
*/
public function tearDown() {
unset($this->Dispatch, $this->Shell);
}
/**
* test available list of test cases for an empty category
*
* @return void
*/
public function testAvailableWithEmptyList() {
$this->Shell->startup();
$this->Shell->args = array('unexistant-category');
$this->Shell->expects($this->at(0))->method('out')->with(__("No test cases available \n\n"));
$this->Shell->expects($this->once())->method('help');
$this->Shell->available();
}
/**
* test available list of test cases for core category
*
* @return void
*/
public function testAvailableCoreCategory() {
$this->Shell->startup();
$this->Shell->args = array('core');
$this->Shell->expects($this->at(0))->method('out')->with('Core Test Cases:');
$this->Shell->expects($this->at(1))->method('out')
->with(new PHPUnit_Framework_Constraint_PCREMatch('/\[1\].*/'));
$this->Shell->expects($this->at(2))->method('out')
->with(new PHPUnit_Framework_Constraint_PCREMatch('/\[2\].*/'));
$this->Shell->expects($this->once())->method('in')
->with(__('What test case would you like to run?'), null, 'q')
->will($this->returnValue('1'));
$this->Shell->expects($this->once())->method('run');
$this->Shell->available();
$this->assertEquals($this->Shell->args, array('core', 'Basics'));
}
/**
* Tests that correct option for test runner are passed
*
* @return void
*/
public function testRunnerOptions() {
$this->Shell->startup();
$this->Shell->args = array('core', 'Basics');
$this->Shell->params = array('filter' => 'myFilter', '-colors' => null, '-verbose' => null);
$this->Shell->expects($this->once())->method('run')
->with(
array('app' => false, 'plugin' => null, 'output' => 'text', 'case' => 'basics'),
array('--colors', '--verbose', '--filter', 'myFilter')
);
$this->Shell->main();
}
}

View file

@ -69,6 +69,15 @@ class TestDispatcher extends Dispatcher {
$this->stopped = true; $this->stopped = true;
return true; return true;
} }
/**
* header method
*
* @return void
*/
public function header() {
}
} }
/** /**
@ -1361,20 +1370,20 @@ class DispatcherTest extends CakeTestCase {
$expected = "alert('plugin one nested js file');"; $expected = "alert('plugin one nested js file');";
$this->assertEqual($result, $expected); $this->assertEqual($result, $expected);
Configure::write('debug', $debug); Configure::write('debug', $debug);
//reset the header content-type without page can render as plain text. //reset the
header('Content-type: text/html');
ob_start(); ob_start();
$Dispatcher->asset('test_plugin/css/unknown.extension'); $Dispatcher->asset('test_plugin/css/unknown.extension');
$result = ob_get_clean(); $result = ob_get_clean();
$this->assertEqual('Testing a file with unknown extension to mime mapping.', $result); $this->assertEqual('Testing a file with unknown extension to mime mapping.', $result);
header('Content-type: text/html');
ob_start(); ob_start();
$Dispatcher->asset('test_plugin/css/theme_one.htc'); $Dispatcher->asset('test_plugin/css/theme_one.htc');
$result = ob_get_clean(); $result = ob_get_clean();
$this->assertEqual('htc file', $result); $this->assertEqual('htc file', $result);
header('Content-type: text/html');
} }
/** /**
@ -1395,7 +1404,7 @@ class DispatcherTest extends CakeTestCase {
$result = ob_get_clean(); $result = ob_get_clean();
$this->assertTrue($Dispatcher->stopped); $this->assertTrue($Dispatcher->stopped);
header('HTTP/1.1 200 Ok');
} }
/** /**

View file

@ -206,7 +206,7 @@ class CacheTest extends CakeTestCase {
Cache::write('test_somthing', 'this is the test data', 'tests'); Cache::write('test_somthing', 'this is the test data', 'tests');
$expected = array( $expected = array(
'path' => TMP . 'sessions', 'path' => TMP . 'sessions' . DS,
'prefix' => 'cake_', 'prefix' => 'cake_',
'lock' => false, 'lock' => false,
'serialize' => true, 'serialize' => true,

View file

@ -215,7 +215,7 @@ class FileEngineTest extends CakeTestCase {
$this->assertFalse(file_exists(CACHE . 'cake_serialize_test2')); $this->assertFalse(file_exists(CACHE . 'cake_serialize_test2'));
$this->assertFalse(file_exists(CACHE . 'cake_serialize_test3')); $this->assertFalse(file_exists(CACHE . 'cake_serialize_test3'));
Cache::config('default', array('engine' => 'File', 'path' => CACHE . 'views')); Cache::config('default', array('engine' => 'File', 'path' => CACHE . 'views' . DS));
$data = 'this is a test of the emergency broadcasting system'; $data = 'this is a test of the emergency broadcasting system';
$write = Cache::write('controller_view_1', $data); $write = Cache::write('controller_view_1', $data);

View file

@ -463,6 +463,35 @@ class ControllerTest extends CakeTestCase {
unset($Controller); unset($Controller);
} }
/**
* testLoadModel method from a plugin controller
*
* @access public
* @return void
*/
function testLoadModelInPlugins() {
App::build(array(
'plugins' => array(TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'plugins' . DS),
'controllers' => array(TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'controllers' . DS),
'models' => array(TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'models' . DS)
));
App::import('Controller', 'TestPlugin.TestPlugin');
$Controller = new TestPluginController();
$Controller->plugin = 'TestPlugin';
$Controller->uses = false;
$this->assertFalse(isset($Controller->Comment));
$result = $Controller->loadModel('Comment');
$this->assertTrue($result);
$this->assertType('Comment', $Controller->Comment);
$this->assertTrue(in_array('Comment', $Controller->modelNames));
ClassRegistry::flush();
unset($Controller);
}
/** /**
* testConstructClasses method * testConstructClasses method
* *

View file

@ -272,6 +272,9 @@ class TestBehavior extends ModelBehavior {
* @return void * @return void
*/ */
function beforeTest(&$model) { function beforeTest(&$model) {
if (!isset($model->beforeTestResult)) {
$model->beforeTestResult = array();
}
$model->beforeTestResult[] = strtolower(get_class($this)); $model->beforeTestResult[] = strtolower(get_class($this));
return strtolower(get_class($this)); return strtolower(get_class($this));
} }

View file

@ -50,6 +50,88 @@ class DboMock extends DboSource {
*/ */
class ModelIntegrationTest extends BaseModelTest { class ModelIntegrationTest extends BaseModelTest {
/**
* testAssociationLazyLoading
*
* @group lazyloading
* @return void
*/
public function testAssociationLazyLoading() {
$this->loadFixtures('ArticleFeaturedsTags');
$Article = new ArticleFeatured();
$this->assertTrue(isset($Article->belongsTo['User']));
$this->assertFalse(property_exists($Article, 'User'));
$this->assertType('User', $Article->User);
$this->assertTrue(isset($Article->belongsTo['Category']));
$this->assertFalse(property_exists($Article, 'Category'));
$this->assertTrue(isset($Article->Category));
$this->assertType('Category', $Article->Category);
$this->assertTrue(isset($Article->hasMany['Comment']));
$this->assertFalse(property_exists($Article, 'Comment'));
$this->assertTrue(isset($Article->Comment));
$this->assertType('Comment', $Article->Comment);
$this->assertTrue(isset($Article->hasAndBelongsToMany['Tag']));
//There was not enough information to setup the association (joinTable and associationForeignKey)
//so the model was not lazy loaded
$this->assertTrue(property_exists($Article, 'Tag'));
$this->assertTrue(isset($Article->Tag));
$this->assertType('Tag', $Article->Tag);
$this->assertFalse(property_exists($Article, 'ArticleFeaturedsTag'));
$this->assertType('AppModel', $Article->ArticleFeaturedsTag);
$this->assertEquals($Article->hasAndBelongsToMany['Tag']['joinTable'], 'article_featureds_tags');
$this->assertEquals($Article->hasAndBelongsToMany['Tag']['associationForeignKey'], 'tag_id');
}
/**
* testAssociationLazyLoadWithHABTM
*
* @group lazyloading
* @return void
*/
public function testAssociationLazyLoadWithHABTM() {
$this->loadFixtures('FruitsUuidTag', 'ArticlesTag');
$Article = new ArticleB();
$this->assertTrue(isset($Article->hasAndBelongsToMany['TagB']));
$this->assertFalse(property_exists($Article, 'TagB'));
$this->assertType('TagB', $Article->TagB);
$this->assertFalse(property_exists($Article, 'ArticlesTag'));
$this->assertType('AppModel', $Article->ArticlesTag);
$UuidTag = new UuidTag();
$this->assertTrue(isset($UuidTag->hasAndBelongsToMany['Fruit']));
$this->assertFalse(property_exists($UuidTag, 'Fruit'));
$this->assertFalse(property_exists($UuidTag, 'FruitsUuidTag'));
$this->assertTrue(isset($UuidTag->Fruit));
$this->assertFalse(property_exists($UuidTag, 'FruitsUuidTag'));
$this->assertTrue(isset($UuidTag->FruitsUuidTag));
$this->assertType('FruitsUuidTag', $UuidTag->FruitsUuidTag);
}
/**
* testAssociationLazyLoadWithBindModel
*
* @group lazyloading
* @return void
*/
public function testAssociationLazyLoadWithBindModel() {
$this->loadFixtures('Article', 'User');
$Article = new ArticleB();
$this->assertFalse(isset($Article->belongsTo['User']));
$this->assertFalse(property_exists($Article, 'User'));
$Article->bindModel(array('belongsTo' => array('User')));
$this->assertTrue(isset($Article->belongsTo['User']));
$this->assertFalse(property_exists($Article, 'User'));
$this->assertType('User', $Article->User);
}
/** /**
* testPkInHAbtmLinkModelArticleB * testPkInHAbtmLinkModelArticleB
* *
@ -96,7 +178,7 @@ class ModelIntegrationTest extends BaseModelTest {
$this->assertEqual($TestModel->ContentAccount->primaryKey, 'iContentAccountsId'); $this->assertEqual($TestModel->ContentAccount->primaryKey, 'iContentAccountsId');
//test conformant models with no PK in the join table //test conformant models with no PK in the join table
$this->loadFixtures('Article', 'Tag', 'User', 'Comment', 'Attachment', 'Syfile', 'Image', 'Item', 'Portfolio', 'ItemsPortfolio'); $this->loadFixtures('Article', 'Tag');
$TestModel2 = new Article(); $TestModel2 = new Article();
$this->assertEqual($TestModel2->ArticlesTag->primaryKey, 'article_id'); $this->assertEqual($TestModel2->ArticlesTag->primaryKey, 'article_id');
@ -874,7 +956,7 @@ class ModelIntegrationTest extends BaseModelTest {
* @return void * @return void
*/ */
function testLoadModelSecondIteration() { function testLoadModelSecondIteration() {
$this->loadFixtures('Message', 'Thread', 'Bid'); $this->loadFixtures('Apple', 'Message', 'Thread', 'Bid');
$model = new ModelA(); $model = new ModelA();
$this->assertIsA($model,'ModelA'); $this->assertIsA($model,'ModelA');
@ -1063,7 +1145,7 @@ class ModelIntegrationTest extends BaseModelTest {
* @return void * @return void
*/ */
function testGetAssociated() { function testGetAssociated() {
$this->loadFixtures('Article', 'Category'); $this->loadFixtures('Article', 'Tag');
$Article = ClassRegistry::init('Article'); $Article = ClassRegistry::init('Article');
$assocTypes = array('hasMany', 'hasOne', 'belongsTo', 'hasAndBelongsToMany'); $assocTypes = array('hasMany', 'hasOne', 'belongsTo', 'hasAndBelongsToMany');
@ -1117,6 +1199,7 @@ class ModelIntegrationTest extends BaseModelTest {
'foreignKey' => false, 'foreignKey' => false,
'className' => 'AssociationTest2', 'className' => 'AssociationTest2',
'with' => 'JoinAsJoinB', 'with' => 'JoinAsJoinB',
'dynamicWith' => true,
'associationForeignKey' => 'join_b_id', 'associationForeignKey' => 'join_b_id',
'conditions' => '', 'fields' => '', 'order' => '', 'limit' => '', 'offset' => '', 'conditions' => '', 'fields' => '', 'order' => '', 'limit' => '', 'offset' => '',
'finderQuery' => '', 'deleteQuery' => '', 'insertQuery' => '' 'finderQuery' => '', 'deleteQuery' => '', 'insertQuery' => ''
@ -1187,6 +1270,7 @@ class ModelIntegrationTest extends BaseModelTest {
'className' => 'Tag', 'className' => 'Tag',
'joinTable' => 'article_featureds_tags', 'joinTable' => 'article_featureds_tags',
'with' => 'ArticleFeaturedsTag', 'with' => 'ArticleFeaturedsTag',
'dynamicWith' => true,
'foreignKey' => 'article_featured_id', 'foreignKey' => 'article_featured_id',
'associationForeignKey' => 'tag_id', 'associationForeignKey' => 'tag_id',
'conditions' => '', 'conditions' => '',
@ -1215,7 +1299,7 @@ class ModelIntegrationTest extends BaseModelTest {
* @return void * @return void
*/ */
function testConstruct() { function testConstruct() {
$this->loadFixtures('Post', 'Comment'); $this->loadFixtures('Post');
$TestModel = ClassRegistry::init('MergeVarPluginPost'); $TestModel = ClassRegistry::init('MergeVarPluginPost');
$this->assertEqual($TestModel->actsAs, array('Containable', 'Tree')); $this->assertEqual($TestModel->actsAs, array('Containable', 'Tree'));

View file

@ -4571,7 +4571,7 @@ class ModelReadTest extends BaseModelTest {
* @return void * @return void
*/ */
function testBindMultipleTimes() { function testBindMultipleTimes() {
$this->loadFixtures('User', 'Comment', 'Article'); $this->loadFixtures('User', 'Comment', 'Article', 'Tag', 'ArticlesTag');
$TestModel = new User(); $TestModel = new User();
$result = $TestModel->hasMany; $result = $TestModel->hasMany;
@ -4587,6 +4587,7 @@ class ModelReadTest extends BaseModelTest {
$result = $TestModel->find('all', array( $result = $TestModel->find('all', array(
'fields' => 'User.id, User.user' 'fields' => 'User.id, User.user'
)); ));
$expected = array( $expected = array(
array( array(
'User' => array( 'User' => array(
@ -4654,7 +4655,9 @@ class ModelReadTest extends BaseModelTest {
), ),
array( array(
'User' => array( 'User' => array(
'id' => '4', 'user' => 'garrett'), 'id' => '4',
'user' => 'garrett'
),
'Items' => array( 'Items' => array(
array( array(
'id' => '2', 'id' => '2',
@ -4730,6 +4733,7 @@ class ModelReadTest extends BaseModelTest {
), ),
'Items' => array() 'Items' => array()
)); ));
$this->assertEqual($result, $expected); $this->assertEqual($result, $expected);
} }

View file

@ -1483,7 +1483,7 @@ class ModelWriteTest extends BaseModelTest {
$this->loadFixtures('JoinA', 'JoinC', 'JoinAC', 'JoinB', 'JoinAB'); $this->loadFixtures('JoinA', 'JoinC', 'JoinAC', 'JoinB', 'JoinAB');
$TestModel = new JoinA(); $TestModel = new JoinA();
$TestModel->hasBelongsToMany['JoinC']['unique'] = true; $TestModel->hasBelongsToMany = array('JoinC' => array('unique' => true));
$data = array( $data = array(
'JoinA' => array( 'JoinA' => array(
'id' => 1, 'id' => 1,
@ -2957,14 +2957,21 @@ class ModelWriteTest extends BaseModelTest {
function testSaveAllTransactionNoRollback() { function testSaveAllTransactionNoRollback() {
$this->loadFixtures('Post'); $this->loadFixtures('Post');
Mock::generate('DboSource', 'MockTransactionDboSource'); $this->getMock('DboSource', array(), array(), 'MockTransactionDboSource');
$db = ConnectionManager::create('mock_transaction', array( $db = ConnectionManager::create('mock_transaction', array(
'datasource' => 'MockTransactionDbo', 'datasource' => 'MockTransactionDbo',
)); ));
$db->expectOnce('rollback'); $db->expects($this->at(2))
->method('isInterfaceSupported')
->with('describe')
->will($this->returnValue(true));
$Post =& new Post(); $db->expects($this->once())
$Post->useDbConfig = 'mock_transaction'; ->method('describe')
->will($this->returnValue(array()));
$db->expects($this->once())->method('rollback');
$Post = new Post('mock_transaction');
$Post->validate = array( $Post->validate = array(
'title' => array('rule' => array('notEmpty')) 'title' => array('rule' => array('notEmpty'))
@ -2994,7 +3001,7 @@ class ModelWriteTest extends BaseModelTest {
array('author_id' => 1, 'title' => '') array('author_id' => 1, 'title' => '')
); );
$ts = date('Y-m-d H:i:s'); $ts = date('Y-m-d H:i:s');
$this->assertEquals($TestModel->saveAll($data), array()); $this->assertFalse($TestModel->saveAll($data));
$result = $TestModel->find('all', array('recursive' => -1)); $result = $TestModel->find('all', array('recursive' => -1));
$expected = array( $expected = array(
@ -3063,7 +3070,7 @@ class ModelWriteTest extends BaseModelTest {
array('author_id' => 1, 'title' => 'New Sixth Post') array('author_id' => 1, 'title' => 'New Sixth Post')
); );
$ts = date('Y-m-d H:i:s'); $ts = date('Y-m-d H:i:s');
$this->assertEquals($TestModel->saveAll($data), array()); $this->assertFalse($TestModel->saveAll($data));
$result = $TestModel->find('all', array('recursive' => -1)); $result = $TestModel->find('all', array('recursive' => -1));
$expected = array( $expected = array(
@ -3261,7 +3268,7 @@ class ModelWriteTest extends BaseModelTest {
'body' => 'Trying to get away with an empty title' 'body' => 'Trying to get away with an empty title'
)); ));
$result = $TestModel->saveAll($data); $result = $TestModel->saveAll($data);
$this->assertEqual($result, array()); $this->assertFalse($result);
$result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC')); $result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC'));
$errors = array(1 => array('title' => 'This field cannot be left blank')); $errors = array(1 => array('title' => 'This field cannot be left blank'));
@ -3347,7 +3354,7 @@ class ModelWriteTest extends BaseModelTest {
'title' => '', 'title' => '',
'body' => 'Trying to get away with an empty title' 'body' => 'Trying to get away with an empty title'
)); ));
$this->assertEquals($TestModel->saveAll($data, array('validate' => 'first')), array()); $this->assertFalse($TestModel->saveAll($data, array('validate' => 'first')));
$result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC')); $result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC'));
$this->assertEqual($result, $expected); $this->assertEqual($result, $expected);

View file

@ -52,13 +52,13 @@ class OptionEngineHelper extends JsBaseEngineHelper {
function event($type, $callback, $options = array()) {} function event($type, $callback, $options = array()) {}
function domReady($functionBody) {} function domReady($functionBody) {}
function each($callback) {} function each($callback) {}
function effect($name, $options) {} function effect($name, $options = array()) {}
function request($url, $options = array()) {} function request($url, $options = array()) {}
function drag($options = array()) {} function drag($options = array()) {}
function drop($options = array()) {} function drop($options = array()) {}
function sortable() {} function sortable($options = array()) {}
function slider() {} function slider($options = array()) {}
function serializeForm() {} function serializeForm($options = array()) {}
} }
/** /**

View file

@ -17,7 +17,9 @@
* @since CakePHP(tm) v 1.2.0.4206 * @since CakePHP(tm) v 1.2.0.4206
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License * @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
*/ */
App::import('Core', array('Theme', 'Controller')); App::import('View', 'View');
App::import('View', 'Theme');
App::import('Core', 'Controller');
if (!class_exists('ErrorHandler')) { if (!class_exists('ErrorHandler')) {
App::import('Core', array('Error')); App::import('Core', array('Error'));
@ -298,9 +300,6 @@ class ThemeViewTest extends CakeTestCase {
* @return void * @return void
*/ */
function testMemoryLeakInPaths() { function testMemoryLeakInPaths() {
if ($this->skipIf(!function_exists('memory_get_usage'), 'No memory measurement function, cannot test for possible memory leak. %s')) {
return;
}
$this->Controller->plugin = null; $this->Controller->plugin = null;
$this->Controller->name = 'Posts'; $this->Controller->name = 'Posts';
$this->Controller->viewPath = 'posts'; $this->Controller->viewPath = 'posts';

View file

@ -0,0 +1,59 @@
<?php
/**
* BakeArticleFixture
*
* PHP 5
*
* CakePHP(tm) Tests <http://book.cakephp.org/view/1196/Testing>
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The Open Group Test Suite License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests
* @package cake
* @subpackage cake.tests.fixtures
* @since CakePHP(tm) v 2.0
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
*/
/**
* Short description for class.
*
* @package cake
* @subpackage cake.tests.fixtures
*/
class BakeArticleFixture extends CakeTestFixture {
/**
* name property
*
* @var string
*/
public $name = 'BakeArticle';
/**
* fields property
*
* @var array
* @access public
*/
public $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary'),
'bake_user_id' => array('type' => 'integer', 'null' => false),
'title' => array('type' => 'string', 'null' => false),
'body' => 'text',
'published' => array('type' => 'string', 'length' => 1, 'default' => 'N'),
'created' => 'datetime',
'updated' => 'datetime'
);
/**
* records property
*
* @var array
* @access public
*/
public $records = array();
}

View file

@ -0,0 +1,56 @@
<?php
/**
* BakeCommentFixture
*
* PHP 5
*
* CakePHP(tm) Tests <http://book.cakephp.org/view/1196/Testing>
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests
* @package cake
* @subpackage cake.tests.fixtures
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* Short description for class.
*
* @package cake
* @subpackage cake.tests.fixtures
*/
class BakeArticlesBakeTagFixture extends CakeTestFixture {
/**
* name property
*
* @var string 'ArticlesTag'
* @access public
*/
public $name = 'BakeArticlesBakeTag';
/**
* fields property
*
* @var array
* @access public
*/
public $fields = array(
'bake_article_id' => array('type' => 'integer', 'null' => false),
'bake_tag_id' => array('type' => 'integer', 'null' => false),
'indexes' => array('UNIQUE_TAG' => array('column'=> array('bake_article_id', 'bake_tag_id'), 'unique'=>1))
);
/**
* records property
*
* @var array
* @access public
*/
public $records = array();
}

View file

@ -0,0 +1,60 @@
<?php
/**
* BakeCommentFixture
*
* PHP 5
*
* CakePHP(tm) Tests <http://book.cakephp.org/view/1196/Testing>
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests
* @package cake
* @subpackage cake.tests.fixtures
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* BakeCommentFixture fixture for testing bake
*
* @package cake
* @subpackage cake.tests.fixtures
*/
class BakeCommentFixture extends CakeTestFixture {
/**
* name property
*
* @var string 'Comment'
* @access public
*/
public $name = 'BakeComment';
/**
* fields property
*
* @var array
* @access public
*/
public $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary'),
'bake_article_id' => array('type' => 'integer', 'null'=>false),
'bake_user_id' => array('type' => 'integer', 'null'=>false),
'comment' => 'text',
'published' => array('type' => 'string', 'length' => 1, 'default' => 'N'),
'created' => 'datetime',
'updated' => 'datetime'
);
/**
* records property
*
* @var array
* @access public
*/
public $records = array();
}

View file

@ -0,0 +1,57 @@
<?php
/**
* BakeTagFixture
*
* PHP 5
*
* CakePHP(tm) Tests <http://book.cakephp.org/view/1196/Testing>
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests
* @package cake
* @subpackage cake.tests.fixtures
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* Short description for class.
*
* @package cake
* @subpackage cake.tests.fixtures
*/
class BakeTagFixture extends CakeTestFixture {
/**
* name property
*
* @var string 'Tag'
* @access public
*/
public $name = 'BakeTag';
/**
* fields property
*
* @var array
* @access public
*/
public $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary'),
'tag' => array('type' => 'string', 'null' => false),
'created' => 'datetime',
'updated' => 'datetime'
);
/**
* records property
*
* @var array
* @access public
*/
public $records = array();
}

View file

@ -118,7 +118,21 @@ class CakeTestSuiteDispatcher {
* *
* @return void * @return void
*/ */
function _checkPHPUnit() { protected function _checkPHPUnit() {
$found = $this->loadTestFramework();
if (!$found) {
$baseDir = $this->_baseDir;
include CAKE_TESTS_LIB . 'templates/phpunit.php';
exit();
}
}
/**
* Checks for the existence of the test framework files
*
* @return boolean true if found, false otherwise
*/
public function loadTestFramework() {
$found = $path = null; $found = $path = null;
if (@include 'PHPUnit' . DS . 'Framework.php') { if (@include 'PHPUnit' . DS . 'Framework.php') {
@ -136,15 +150,11 @@ class CakeTestSuiteDispatcher {
$found = include 'PHPUnit' . DS . 'Framework.php'; $found = include 'PHPUnit' . DS . 'Framework.php';
} }
} }
if ($found) {
if (!$found) {
$baseDir = $this->_baseDir;
include CAKE_TESTS_LIB . 'templates/phpunit.php';
exit();
}
PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'DEFAULT'); PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'DEFAULT');
} }
return $found;
}
/** /**
* Checks for the xdebug extension required to do code coverage. Displays an error * Checks for the xdebug extension required to do code coverage. Displays an error

View file

@ -159,7 +159,7 @@ class CakeBaseReporter implements PHPUnit_Framework_TestListener {
* @param float $time * @param float $time
*/ */
public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) { public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) {
$this->paintException($e); $this->paintException($e, $test);
} }
/** /**
@ -170,7 +170,7 @@ class CakeBaseReporter implements PHPUnit_Framework_TestListener {
* @param float $time * @param float $time
*/ */
public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) { public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) {
$this->paintFail($e); $this->paintFail($e, $test);
} }
/** /**

View file

@ -227,29 +227,16 @@ class CakeHtmlReporter extends CakeBaseReporter {
* the context of the other tests. * the context of the other tests.
* @return void * @return void
*/ */
public function paintFail($message) { public function paintFail($message, $test) {
$context = $message->getTrace(); $trace = $this->_getStackTrace($message);
$realContext = $context[3]; $testName = get_class($test) . '(' . $test->getName() . ')';
$class = new ReflectionClass($realContext['class']);
$deeper = false;
if ($class->getParentClass()) {
$deeper = $class->getParentClass()->getName() === 'PHPUnit_Framework_TestCase';
}
$deeper = $deeper || !$class->isSubclassOf('PHPUnit_Framework_TestCase');
if ($deeper) {
$realContext = $context[4];
$context = $context[3];
} else {
$context = $context[2];
}
echo "<li class='fail'>\n"; echo "<li class='fail'>\n";
echo "<span>Failed</span>"; echo "<span>Failed</span>";
echo "<div class='msg'><pre>" . $this->_htmlEntities($message->toString()) . "</pre></div>\n"; echo "<div class='msg'><pre>" . $this->_htmlEntities($message->toString()) . "</pre></div>\n";
echo "<div class='msg'>" . sprintf(__('File: %s'), $context['file']) . "</div>\n";
echo "<div class='msg'>" . sprintf(__('Method: %s'), $realContext['function']) . "</div>\n"; echo "<div class='msg'>" . sprintf(__('Test case: %s'), $testName) . "</div>\n";
echo "<div class='msg'>" . sprintf(__('Line: %s'), $context['line']) . "</div>\n"; echo "<div class='msg'>" . __('Stack trace:') . '<br />' . $trace . "</div>\n";
echo "</li>\n"; echo "</li>\n";
} }
@ -278,7 +265,7 @@ class CakeHtmlReporter extends CakeBaseReporter {
* @param Exception $exception Exception to display. * @param Exception $exception Exception to display.
* @return void * @return void
*/ */
public function paintException($exception) { public function paintException($exception, $test) {
echo "<li class='fail'>\n"; echo "<li class='fail'>\n";
echo "<span>Exception</span>"; echo "<span>Exception</span>";
$message = 'Unexpected exception of type [' . get_class($exception) . $message = 'Unexpected exception of type [' . get_class($exception) .
@ -323,6 +310,21 @@ class CakeHtmlReporter extends CakeBaseReporter {
return htmlentities($message, ENT_COMPAT, $this->_characterSet); return htmlentities($message, ENT_COMPAT, $this->_characterSet);
} }
/**
* Gets a formatted stack trace.
*
* @param Exception $e Exception to get a stack trace for.
* @return string Generated stack trace.
*/
protected function _getStackTrace(Exception $e) {
$trace = $e->getTrace();
$out = array();
foreach ($trace as $frame) {
$out[] = $frame['file'] . ' : ' . $frame['line'];
}
return implode('<br />', $out);
}
/** /**
* A test suite started. * A test suite started.
* *

View file

@ -75,6 +75,13 @@ class TestManager {
*/ */
protected $_fixtureManager = null; protected $_fixtureManager = null;
/**
* Params to configure test runner
*
* @var CakeFixtureManager
*/
public $params = array();
/** /**
* Constructor for the TestManager class * Constructor for the TestManager class
* *
@ -82,6 +89,8 @@ class TestManager {
*/ */
public function __construct($params = array()) { public function __construct($params = array()) {
require_once(CAKE_TESTS_LIB . 'cake_test_case.php'); require_once(CAKE_TESTS_LIB . 'cake_test_case.php');
$this->params = $params;
if (isset($params['app'])) { if (isset($params['app'])) {
$this->appTest = true; $this->appTest = true;
} }
@ -130,14 +139,7 @@ class TestManager {
* @return mixed Result of test case being run. * @return mixed Result of test case being run.
*/ */
public function runTestCase($testCaseFile, PHPUnit_Framework_TestListener $reporter, $codeCoverage = false) { public function runTestCase($testCaseFile, PHPUnit_Framework_TestListener $reporter, $codeCoverage = false) {
$testCaseFileWithPath = $this->_getTestsPath($reporter->params) . DS . $testCaseFile; $this->loadCase($testCaseFile);
if (!file_exists($testCaseFileWithPath) || strpos($testCaseFileWithPath, '..')) {
throw new InvalidArgumentException(sprintf(__('Unable to load test file %s'), htmlentities($testCaseFile)));
}
$testSuite = $this->getTestSuite(sprintf(__('Individual test case: %s', true), $testCaseFile));
$testSuite->addTestFile($testCaseFileWithPath);
return $this->run($reporter, $codeCoverage); return $this->run($reporter, $codeCoverage);
} }
@ -162,6 +164,28 @@ class TestManager {
return $result; return $result;
} }
/**
* Loads a test case in a test suite, if the test suite is null it will create it
*
* @param string Test file path
* @param PHPUnit_Framework_TestSuite $suite the test suite to load the case in
* @throws InvalidArgumentException if test case file is not found
* @return PHPUnit_Framework_TestSuite the suite with the test case loaded
*/
public function loadCase($testCaseFile, PHPUnit_Framework_TestSuite $suite = null) {
$testCaseFileWithPath = $this->_getTestsPath($this->params) . DS . $testCaseFile;
if (!file_exists($testCaseFileWithPath) || strpos($testCaseFileWithPath, '..')) {
throw new InvalidArgumentException(sprintf(__('Unable to load test file %s'), htmlentities($testCaseFile)));
}
if (!$suite) {
$suite = $this->getTestSuite(sprintf(__('Individual test case: %s', true), $testCaseFile));
}
$suite->addTestFile($testCaseFileWithPath);
return $suite;
}
/** /**
* Adds all testcases in a given directory to a given GroupTest object * Adds all testcases in a given directory to a given GroupTest object
* *
@ -313,7 +337,7 @@ class TestManager {
* @param string $name The name for the container test suite * @param string $name The name for the container test suite
* @return PHPUnit_Framework_TestSuite container test suite * @return PHPUnit_Framework_TestSuite container test suite
*/ */
protected function getTestSuite($name = '') { public function getTestSuite($name = '') {
if (!empty($this->_testSuite)) { if (!empty($this->_testSuite)) {
return $this->_testSuite; return $this->_testSuite;
} }
@ -325,7 +349,7 @@ class TestManager {
* *
* @return CakeFixtureManager fixture manager * @return CakeFixtureManager fixture manager
*/ */
protected function getFixtureManager() { public function getFixtureManager() {
if (!empty($this->_fixtureManager)) { if (!empty($this->_fixtureManager)) {
return $this->_fixtureManager; return $this->_fixtureManager;
} }

View file

@ -0,0 +1,59 @@
<?php
/**
* TestRunner for CakePHP Test suite.
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package cake
* @subpackage cake.cake.tests.libs
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
require 'PHPUnit/TextUI/Command.php';
require_once 'test_manager.php';
PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'DEFAULT');
/**
* Class to customize loading of test suites from CLI
*
* @package cake
* @subpackage cake.cake.tests.lib
*/
class TestRunner extends PHPUnit_TextUI_Command {
/**
* Construct method
*
* @param array $params list of options to be used for this run
*/
public function __construct($params = array()) {
$this->_params = $params;
}
/**
* Sets the proper test suite to use and loads the test file in it.
* this method gets called as a callback from the parent class
*
* @return void
*/
protected function handleCustomTestSuite() {
$manager = new TestManager($this->_params);
if (!empty($this->_params['case'])) {
$this->arguments['test'] = $manager->getTestSuite();
$this->arguments['test']->setFixtureManager($manager->getFixtureManager());
$manager->loadCase($this->_params['case'] . '.test.php', $this->arguments['test']);
}
}
}