Merge pull request #3979 from dhensby/pulls/test-nest

Nest and unnest Config and Controller for each test
This commit is contained in:
Damian Mooyman 2015-06-17 16:04:27 +12:00
commit 0653ba9630
10 changed files with 305 additions and 333 deletions

View File

@ -5,12 +5,12 @@ require_once 'TestRunner.php';
* Test case class for the Sapphire framework. * Test case class for the Sapphire framework.
* Sapphire unit testing is based on PHPUnit, but provides a number of hooks into our data model that make it easier * Sapphire unit testing is based on PHPUnit, but provides a number of hooks into our data model that make it easier
* to work with. * to work with.
* *
* @package framework * @package framework
* @subpackage testing * @subpackage testing
*/ */
class SapphireTest extends PHPUnit_Framework_TestCase { class SapphireTest extends PHPUnit_Framework_TestCase {
/** @config */ /** @config */
private static $dependencies = array( private static $dependencies = array(
'fixtureFactory' => '%$FixtureFactory', 'fixtureFactory' => '%$FixtureFactory',
@ -21,7 +21,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
* If passed as an array, multiple fixture files will be loaded. * If passed as an array, multiple fixture files will be loaded.
* Please note that you won't be able to refer with "=>" notation * Please note that you won't be able to refer with "=>" notation
* between the fixtures, they act independent of each other. * between the fixtures, they act independent of each other.
* *
* @var string|array * @var string|array
*/ */
protected static $fixture_file = null; protected static $fixture_file = null;
@ -30,19 +30,19 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
* @var FixtureFactory * @var FixtureFactory
*/ */
protected $fixtureFactory; protected $fixtureFactory;
/** /**
* @var bool Set whether to include this test in the TestRunner or to skip this. * @var bool Set whether to include this test in the TestRunner or to skip this.
*/ */
protected $skipTest = false; protected $skipTest = false;
/** /**
* @var Boolean If set to TRUE, this will force a test database to be generated * @var Boolean If set to TRUE, this will force a test database to be generated
* in {@link setUp()}. Note that this flag is overruled by the presence of a * in {@link setUp()}. Note that this flag is overruled by the presence of a
* {@link $fixture_file}, which always forces a database build. * {@link $fixture_file}, which always forces a database build.
*/ */
protected $usesDatabase = null; protected $usesDatabase = null;
protected $originalMailer; protected $originalMailer;
protected $originalMemberPasswordValidator; protected $originalMemberPasswordValidator;
protected $originalRequirements; protected $originalRequirements;
@ -50,33 +50,33 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
protected $originalTheme; protected $originalTheme;
protected $originalNestedURLsState; protected $originalNestedURLsState;
protected $originalMemoryLimit; protected $originalMemoryLimit;
protected $mailer; protected $mailer;
/** /**
* Pointer to the manifest that isn't a test manifest * Pointer to the manifest that isn't a test manifest
*/ */
protected static $regular_manifest; protected static $regular_manifest;
/** /**
* @var boolean * @var boolean
*/ */
protected static $is_running_test = false; protected static $is_running_test = false;
protected static $test_class_manifest; protected static $test_class_manifest;
/** /**
* By default, setUp() does not require default records. Pass * By default, setUp() does not require default records. Pass
* class names in here, and the require/augment default records * class names in here, and the require/augment default records
* function will be called on them. * function will be called on them.
*/ */
protected $requireDefaultRecordsFrom = array(); protected $requireDefaultRecordsFrom = array();
/** /**
* A list of extensions that can't be applied during the execution of this run. If they are * A list of extensions that can't be applied during the execution of this run. If they are
* applied, they will be temporarily removed and a database migration called. * applied, they will be temporarily removed and a database migration called.
* *
* The keys of the are the classes that the extensions can't be applied the extensions to, and * The keys of the are the classes that the extensions can't be applied the extensions to, and
* the values are an array of illegal extensions on that class. * the values are an array of illegal extensions on that class.
*/ */
@ -86,10 +86,10 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
/** /**
* A list of extensions that must be applied during the execution of this run. If they are * A list of extensions that must be applied during the execution of this run. If they are
* not applied, they will be temporarily added and a database migration called. * not applied, they will be temporarily added and a database migration called.
* *
* The keys of the are the classes to apply the extensions to, and the values are an array * The keys of the are the classes to apply the extensions to, and the values are an array
* of required extensions on that class. * of required extensions on that class.
* *
* Example: * Example:
* <code> * <code>
* array("MyTreeDataObject" => array("Versioned", "Hierarchy")) * array("MyTreeDataObject" => array("Versioned", "Hierarchy"))
@ -97,35 +97,35 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
*/ */
protected $requiredExtensions = array( protected $requiredExtensions = array(
); );
/** /**
* By default, the test database won't contain any DataObjects that have the interface TestOnly. * By default, the test database won't contain any DataObjects that have the interface TestOnly.
* This variable lets you define additional TestOnly DataObjects to set up for this test. * This variable lets you define additional TestOnly DataObjects to set up for this test.
* Set it to an array of DataObject subclass names. * Set it to an array of DataObject subclass names.
*/ */
protected $extraDataObjects = array(); protected $extraDataObjects = array();
/** /**
* We need to disabling backing up of globals to avoid overriding * We need to disabling backing up of globals to avoid overriding
* the few globals SilverStripe relies on, like $lang for the i18n subsystem. * the few globals SilverStripe relies on, like $lang for the i18n subsystem.
* *
* @see http://sebastian-bergmann.de/archives/797-Global-Variables-and-PHPUnit.html * @see http://sebastian-bergmann.de/archives/797-Global-Variables-and-PHPUnit.html
*/ */
protected $backupGlobals = FALSE; protected $backupGlobals = FALSE;
/** /**
* Helper arrays for illegalExtensions/requiredExtensions code * Helper arrays for illegalExtensions/requiredExtensions code
*/ */
private $extensionsToReapply = array(), $extensionsToRemove = array(); private $extensionsToReapply = array(), $extensionsToRemove = array();
/** /**
* Determines if unit tests are currently run (via {@link TestRunner}). * Determines if unit tests are currently run (via {@link TestRunner}).
* This is used as a cheap replacement for fully mockable state * This is used as a cheap replacement for fully mockable state
* in certain contiditions (e.g. access checks). * in certain contiditions (e.g. access checks).
* Caution: When set to FALSE, certain controllers might bypass * Caution: When set to FALSE, certain controllers might bypass
* access checks, so this is a very security sensitive setting. * access checks, so this is a very security sensitive setting.
* *
* @return boolean * @return boolean
*/ */
public static function is_running_test() { public static function is_running_test() {
@ -133,7 +133,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
} }
public static function set_is_running_test($bool) { public static function set_is_running_test($bool) {
self::$is_running_test = $bool; self::$is_running_test = $bool;
} }
/** /**
@ -161,22 +161,27 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
* @var array $fixtures Array of {@link YamlFixture} instances * @var array $fixtures Array of {@link YamlFixture} instances
* @deprecated 3.1 Use $fixtureFactory instad * @deprecated 3.1 Use $fixtureFactory instad
*/ */
protected $fixtures = array(); protected $fixtures = array();
protected $model; protected $model;
public function setUp() { public function setUp() {
//nest config and injector for each test so they are effectively sandboxed per test
Config::nest();
Injector::nest();
// We cannot run the tests on this abstract class. // We cannot run the tests on this abstract class.
if(get_class($this) == "SapphireTest") $this->skipTest = true; if(get_class($this) == "SapphireTest") $this->skipTest = true;
if($this->skipTest) { if($this->skipTest) {
$this->markTestSkipped(sprintf( $this->markTestSkipped(sprintf(
'Skipping %s ', get_class($this) 'Skipping %s ', get_class($this)
)); ));
return; return;
} }
// Mark test as being run // Mark test as being run
$this->originalIsRunningTest = self::$is_running_test; $this->originalIsRunningTest = self::$is_running_test;
self::$is_running_test = true; self::$is_running_test = true;
@ -185,16 +190,16 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
i18n::set_locale(i18n::default_locale()); i18n::set_locale(i18n::default_locale());
i18n::config()->date_format = null; i18n::config()->date_format = null;
i18n::config()->time_format = null; i18n::config()->time_format = null;
// Set default timezone consistently to avoid NZ-specific dependencies // Set default timezone consistently to avoid NZ-specific dependencies
date_default_timezone_set('UTC'); date_default_timezone_set('UTC');
// Remove password validation // Remove password validation
$this->originalMemberPasswordValidator = Member::password_validator(); $this->originalMemberPasswordValidator = Member::password_validator();
$this->originalRequirements = Requirements::backend(); $this->originalRequirements = Requirements::backend();
Member::set_password_validator(null); Member::set_password_validator(null);
Config::inst()->update('Cookie', 'report_errors', false); Config::inst()->update('Cookie', 'report_errors', false);
if(class_exists('RootURLController')) RootURLController::reset(); if(class_exists('RootURLController')) RootURLController::reset();
if(class_exists('Translatable')) Translatable::reset(); if(class_exists('Translatable')) Translatable::reset();
Versioned::reset(); Versioned::reset();
@ -203,7 +208,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
Hierarchy::reset(); Hierarchy::reset();
if(Controller::has_curr()) Controller::curr()->setSession(Injector::inst()->create('Session', array())); if(Controller::has_curr()) Controller::curr()->setSession(Injector::inst()->create('Session', array()));
Security::$database_is_ready = null; Security::$database_is_ready = null;
$fixtureFile = static::get_fixture_file(); $fixtureFile = static::get_fixture_file();
$prefix = defined('SS_DATABASE_PREFIX') ? SS_DATABASE_PREFIX : 'ss_'; $prefix = defined('SS_DATABASE_PREFIX') ? SS_DATABASE_PREFIX : 'ss_';
@ -213,13 +218,13 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
$this->mailer = new TestMailer(); $this->mailer = new TestMailer();
Email::set_mailer($this->mailer); Email::set_mailer($this->mailer);
Config::inst()->remove('Email', 'send_all_emails_to'); Config::inst()->remove('Email', 'send_all_emails_to');
// Todo: this could be a special test model // Todo: this could be a special test model
$this->model = DataModel::inst(); $this->model = DataModel::inst();
// Set up fixture // Set up fixture
if($fixtureFile || $this->usesDatabase || !self::using_temp_db()) { if($fixtureFile || $this->usesDatabase || !self::using_temp_db()) {
if(substr(DB::getConn()->currentDatabase(), 0, strlen($prefix) + 5) if(substr(DB::getConn()->currentDatabase(), 0, strlen($prefix) + 5)
!= strtolower(sprintf('%stmpdb', $prefix))) { != strtolower(sprintf('%stmpdb', $prefix))) {
//echo "Re-creating temp database... "; //echo "Re-creating temp database... ";
@ -228,9 +233,9 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
} }
singleton('DataObject')->flushCache(); singleton('DataObject')->flushCache();
self::empty_temp_db(); self::empty_temp_db();
foreach($this->requireDefaultRecordsFrom as $className) { foreach($this->requireDefaultRecordsFrom as $className) {
$instance = singleton($className); $instance = singleton($className);
if (method_exists($instance, 'requireDefaultRecords')) $instance->requireDefaultRecords(); if (method_exists($instance, 'requireDefaultRecords')) $instance->requireDefaultRecords();
@ -245,14 +250,14 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
foreach($fixtureFiles as $fixtureFilePath) { foreach($fixtureFiles as $fixtureFilePath) {
// Support fixture paths relative to the test class, rather than relative to webroot // Support fixture paths relative to the test class, rather than relative to webroot
// String checking is faster than file_exists() calls. // String checking is faster than file_exists() calls.
$isRelativeToFile = (strpos('/', $fixtureFilePath) === false $isRelativeToFile = (strpos('/', $fixtureFilePath) === false
|| preg_match('/^\.\./', $fixtureFilePath)); || preg_match('/^\.\./', $fixtureFilePath));
if($isRelativeToFile) { if($isRelativeToFile) {
$resolvedPath = realpath($pathForClass . '/' . $fixtureFilePath); $resolvedPath = realpath($pathForClass . '/' . $fixtureFilePath);
if($resolvedPath) $fixtureFilePath = $resolvedPath; if($resolvedPath) $fixtureFilePath = $resolvedPath;
} }
$fixture = Injector::inst()->create('YamlFixture', $fixtureFilePath); $fixture = Injector::inst()->create('YamlFixture', $fixtureFilePath);
$fixture->writeInto($this->getFixtureFactory()); $fixture->writeInto($this->getFixtureFactory());
$this->fixtures[] = $fixture; $this->fixtures[] = $fixture;
@ -262,20 +267,20 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
$i++; $i++;
} }
} }
$this->logInWithPermission("ADMIN"); $this->logInWithPermission("ADMIN");
} }
// Preserve memory settings // Preserve memory settings
$this->originalMemoryLimit = ini_get('memory_limit'); $this->originalMemoryLimit = ini_get('memory_limit');
// turn off template debugging // turn off template debugging
Config::inst()->update('SSViewer', 'source_file_comments', false); Config::inst()->update('SSViewer', 'source_file_comments', false);
// Clear requirements // Clear requirements
Requirements::clear(); Requirements::clear();
} }
/** /**
* Called once per test case ({@link SapphireTest} subclass). * Called once per test case ({@link SapphireTest} subclass).
* This is different to {@link setUp()}, which gets called once * This is different to {@link setUp()}, which gets called once
@ -285,6 +290,10 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
* for tearing down the state again. * for tearing down the state again.
*/ */
public function setUpOnce() { public function setUpOnce() {
//nest config and injector for each suite so they are effectively sandboxed
Config::nest();
Injector::nest();
$isAltered = false; $isAltered = false;
if(!Director::isDev()) { if(!Director::isDev()) {
@ -315,46 +324,34 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
} }
} }
} }
// If we have made changes to the extensions present, then migrate the database schema. // If we have made changes to the extensions present, then migrate the database schema.
if($isAltered || $this->extensionsToReapply || $this->extensionsToRemove || $this->extraDataObjects) { if($isAltered || $this->extensionsToReapply || $this->extensionsToRemove || $this->extraDataObjects) {
if(!self::using_temp_db()) self::create_temp_db(); if(!self::using_temp_db()) self::create_temp_db();
$this->resetDBSchema(true); $this->resetDBSchema(true);
} }
// clear singletons, they're caching old extension info // clear singletons, they're caching old extension info
// which is used in DatabaseAdmin->doBuild() // which is used in DatabaseAdmin->doBuild()
Injector::inst()->unregisterAllObjects(); Injector::inst()->unregisterAllObjects();
// Set default timezone consistently to avoid NZ-specific dependencies // Set default timezone consistently to avoid NZ-specific dependencies
date_default_timezone_set('UTC'); date_default_timezone_set('UTC');
} }
/** /**
* tearDown method that's called once per test class rather once per test method. * tearDown method that's called once per test class rather once per test method.
*/ */
public function tearDownOnce() { public function tearDownOnce() {
// If we have made changes to the extensions present, then migrate the database schema. //unnest injector / config now that the test suite is over
if($this->extensionsToReapply || $this->extensionsToRemove) { // this will reset all the extensions on the object too (see setUpOnce)
// Remove extensions added for testing Injector::unnest();
foreach($this->extensionsToRemove as $class => $extensions) { Config::unnest();
foreach($extensions as $extension) {
$class::remove_extension($extension);
}
}
// Reapply ones removed if(!empty($this->extensionsToReapply) || !empty($this->extensionsToRemove) || !empty($this->extraDataObjects)) {
foreach($this->extensionsToReapply as $class => $extensions) {
foreach($extensions as $extension) {
$class::add_extension($extension);
}
}
}
if($this->extensionsToReapply || $this->extensionsToRemove || $this->extraDataObjects) {
$this->resetDBSchema(); $this->resetDBSchema();
} }
} }
/** /**
* @return FixtureFactory * @return FixtureFactory
*/ */
@ -367,10 +364,10 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
$this->fixtureFactory = $factory; $this->fixtureFactory = $factory;
return $this; return $this;
} }
/** /**
* Get the ID of an object from the fixture. * Get the ID of an object from the fixture.
* *
* @param $className The data class, as specified in your fixture file. Parent classes won't work * @param $className The data class, as specified in your fixture file. Parent classes won't work
* @param $identifier The identifier string, as provided in your fixture file * @param $identifier The identifier string, as provided in your fixture file
* @return int * @return int
@ -416,12 +413,12 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
"Couldn't find object '%s' (class: %s)", "Couldn't find object '%s' (class: %s)",
$identifier, $identifier,
$className $className
), E_USER_ERROR); ), E_USER_ERROR);
} }
return $obj; return $obj;
} }
/** /**
* Load a YAML fixture file into the database. * Load a YAML fixture file into the database.
* Once loaded, you can use idFromFixture() and objFromFixture() to get items from the fixture. * Once loaded, you can use idFromFixture() and objFromFixture() to get items from the fixture.
@ -434,19 +431,19 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
$fixture->writeInto($this->getFixtureFactory()); $fixture->writeInto($this->getFixtureFactory());
$this->fixtures[] = $fixture; $this->fixtures[] = $fixture;
} }
/** /**
* Clear all fixtures which were previously loaded through * Clear all fixtures which were previously loaded through
* {@link loadFixture()} * {@link loadFixture()}
*/ */
public function clearFixtures() { public function clearFixtures() {
$this->fixtures = array(); $this->fixtures = array();
$this->getFixtureFactory()->clear(); $this->getFixtureFactory()->clear();
} }
/** /**
* Useful for writing unit tests without hardcoding folder structures. * Useful for writing unit tests without hardcoding folder structures.
* *
* @return String Absolute path to current class. * @return String Absolute path to current class.
*/ */
protected function getCurrentAbsolutePath() { protected function getCurrentAbsolutePath() {
@ -454,7 +451,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
if(!$filename) throw new LogicException("getItemPath returned null for " . get_class($this)); if(!$filename) throw new LogicException("getItemPath returned null for " . get_class($this));
return dirname($filename); return dirname($filename);
} }
/** /**
* @return String File path relative to webroot * @return String File path relative to webroot
*/ */
@ -464,7 +461,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
if(substr($path,0,strlen($base)) == $base) $path = preg_replace('/^\/*/', '', substr($path,strlen($base))); if(substr($path,0,strlen($base)) == $base) $path = preg_replace('/^\/*/', '', substr($path,strlen($base)));
return $path; return $path;
} }
public function tearDown() { public function tearDown() {
// Preserve memory settings // Preserve memory settings
ini_set('memory_limit', ($this->originalMemoryLimit) ? $this->originalMemoryLimit : -1); ini_set('memory_limit', ($this->originalMemoryLimit) ? $this->originalMemoryLimit : -1);
@ -474,16 +471,16 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
Email::set_mailer($this->originalMailer); Email::set_mailer($this->originalMailer);
$this->originalMailer = null; $this->originalMailer = null;
} }
$this->mailer = null; $this->mailer = null;
// Restore password validation // Restore password validation
if($this->originalMemberPasswordValidator) { if($this->originalMemberPasswordValidator) {
Member::set_password_validator($this->originalMemberPasswordValidator); Member::set_password_validator($this->originalMemberPasswordValidator);
} }
// Restore requirements // Restore requirements
if($this->originalRequirements) { if($this->originalRequirements) {
Requirements::set_backend($this->originalRequirements); Requirements::set_backend($this->originalRequirements);
} }
// Mark test as no longer being run - we use originalIsRunningTest to allow for nested SapphireTest calls // Mark test as no longer being run - we use originalIsRunningTest to allow for nested SapphireTest calls
@ -492,15 +489,18 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
// Reset mocked datetime // Reset mocked datetime
SS_Datetime::clear_mock_now(); SS_Datetime::clear_mock_now();
// Stop the redirection that might have been requested in the test. // Stop the redirection that might have been requested in the test.
// Note: Ideally a clean Controller should be created for each test. // Note: Ideally a clean Controller should be created for each test.
// Now all tests executed in a batch share the same controller. // Now all tests executed in a batch share the same controller.
$controller = Controller::has_curr() ? Controller::curr() : null; $controller = Controller::has_curr() ? Controller::curr() : null;
if ( $controller && $controller->response && $controller->response->getHeader('Location') ) { if ( $controller && $controller->response && $controller->response->getHeader('Location') ) {
$controller->response->setStatusCode(200); $controller->response->setStatusCode(200);
$controller->response->removeHeader('Location'); $controller->response->removeHeader('Location');
} }
//unnest injector / config now that tests are over
Injector::unnest();
Config::unnest();
} }
public static function assertContains( public static function assertContains(
@ -547,7 +547,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
public function findEmail($to, $from = null, $subject = null, $content = null) { public function findEmail($to, $from = null, $subject = null, $content = null) {
return $this->mailer->findEmail($to, $from, $subject, $content); return $this->mailer->findEmail($to, $from, $subject, $content);
} }
/** /**
* Assert that the matching email was sent since the last call to clearEmails() * Assert that the matching email was sent since the last call to clearEmails()
* All of the parameters can either be a string, or, if they start with "/", a PREG-compatible regular expression. * All of the parameters can either be a string, or, if they start with "/", a PREG-compatible regular expression.
@ -579,7 +579,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
/** /**
* Assert that the given {@link SS_List} includes DataObjects matching the given key-value * Assert that the given {@link SS_List} includes DataObjects matching the given key-value
* pairs. Each match must correspond to 1 distinct record. * pairs. Each match must correspond to 1 distinct record.
* *
* @param $matches The patterns to match. Each pattern is a map of key-value pairs. You can * @param $matches The patterns to match. Each pattern is a map of key-value pairs. You can
* either pass a single pattern or an array of patterns. * either pass a single pattern or an array of patterns.
* @param $dataObjectSet The {@link SS_List} to test. * @param $dataObjectSet The {@link SS_List} to test.
@ -587,19 +587,19 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
* Examples * Examples
* -------- * --------
* Check that $members includes an entry with Email = sam@example.com: * Check that $members includes an entry with Email = sam@example.com:
* $this->assertDOSContains(array('Email' => '...@example.com'), $members); * $this->assertDOSContains(array('Email' => '...@example.com'), $members);
* *
* Check that $members includes entries with Email = sam@example.com and with * Check that $members includes entries with Email = sam@example.com and with
* Email = ingo@example.com: * Email = ingo@example.com:
* $this->assertDOSContains(array( * $this->assertDOSContains(array(
* array('Email' => '...@example.com'), * array('Email' => '...@example.com'),
* array('Email' => 'i...@example.com'), * array('Email' => 'i...@example.com'),
* ), $members); * ), $members);
*/ */
public function assertDOSContains($matches, $dataObjectSet) { public function assertDOSContains($matches, $dataObjectSet) {
$extracted = array(); $extracted = array();
foreach($dataObjectSet as $item) $extracted[] = $item->toMap(); foreach($dataObjectSet as $item) $extracted[] = $item->toMap();
foreach($matches as $match) { foreach($matches as $match) {
$matched = false; $matched = false;
foreach($extracted as $i => $item) { foreach($extracted as $i => $item) {
@ -615,35 +615,35 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
$this->assertTrue( $this->assertTrue(
$matched, $matched,
"Failed asserting that the SS_List contains an item matching " "Failed asserting that the SS_List contains an item matching "
. var_export($match, true) . "\n\nIn the following SS_List:\n" . var_export($match, true) . "\n\nIn the following SS_List:\n"
. $this->DOSSummaryForMatch($dataObjectSet, $match) . $this->DOSSummaryForMatch($dataObjectSet, $match)
); );
} }
} }
/** /**
* Assert that the given {@link SS_List} includes only DataObjects matching the given * Assert that the given {@link SS_List} includes only DataObjects matching the given
* key-value pairs. Each match must correspond to 1 distinct record. * key-value pairs. Each match must correspond to 1 distinct record.
* *
* @param $matches The patterns to match. Each pattern is a map of key-value pairs. You can * @param $matches The patterns to match. Each pattern is a map of key-value pairs. You can
* either pass a single pattern or an array of patterns. * either pass a single pattern or an array of patterns.
* @param $dataObjectSet The {@link SS_List} to test. * @param $dataObjectSet The {@link SS_List} to test.
* *
* Example * Example
* -------- * --------
* Check that *only* the entries Sam Minnee and Ingo Schommer exist in $members. Order doesn't * Check that *only* the entries Sam Minnee and Ingo Schommer exist in $members. Order doesn't
* matter: * matter:
* $this->assertDOSEquals(array( * $this->assertDOSEquals(array(
* array('FirstName' =>'Sam', 'Surname' => 'Minnee'), * array('FirstName' =>'Sam', 'Surname' => 'Minnee'),
* array('FirstName' => 'Ingo', 'Surname' => 'Schommer'), * array('FirstName' => 'Ingo', 'Surname' => 'Schommer'),
* ), $members); * ), $members);
*/ */
public function assertDOSEquals($matches, $dataObjectSet) { public function assertDOSEquals($matches, $dataObjectSet) {
if(!$dataObjectSet) return false; if(!$dataObjectSet) return false;
$extracted = array(); $extracted = array();
foreach($dataObjectSet as $item) $extracted[] = $item->toMap(); foreach($dataObjectSet as $item) $extracted[] = $item->toMap();
foreach($matches as $match) { foreach($matches as $match) {
$matched = false; $matched = false;
foreach($extracted as $i => $item) { foreach($extracted as $i => $item) {
@ -659,11 +659,11 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
$this->assertTrue( $this->assertTrue(
$matched, $matched,
"Failed asserting that the SS_List contains an item matching " "Failed asserting that the SS_List contains an item matching "
. var_export($match, true) . "\n\nIn the following SS_List:\n" . var_export($match, true) . "\n\nIn the following SS_List:\n"
. $this->DOSSummaryForMatch($dataObjectSet, $match) . $this->DOSSummaryForMatch($dataObjectSet, $match)
); );
} }
// If we have leftovers than the DOS has extra data that shouldn't be there // If we have leftovers than the DOS has extra data that shouldn't be there
$this->assertTrue( $this->assertTrue(
(count($extracted) == 0), (count($extracted) == 0),
@ -671,19 +671,19 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
"Failed asserting that the SS_List contained only the given items, the " "Failed asserting that the SS_List contained only the given items, the "
. "following items were left over:\n" . var_export($extracted, true) . "following items were left over:\n" . var_export($extracted, true)
); );
} }
/** /**
* Assert that the every record in the given {@link SS_List} matches the given key-value * Assert that the every record in the given {@link SS_List} matches the given key-value
* pairs. * pairs.
* *
* @param $match The pattern to match. The pattern is a map of key-value pairs. * @param $match The pattern to match. The pattern is a map of key-value pairs.
* @param $dataObjectSet The {@link SS_List} to test. * @param $dataObjectSet The {@link SS_List} to test.
* *
* Example * Example
* -------- * --------
* Check that every entry in $members has a Status of 'Active': * Check that every entry in $members has a Status of 'Active':
* $this->assertDOSAllMatch(array('Status' => 'Active'), $members); * $this->assertDOSAllMatch(array('Status' => 'Active'), $members);
*/ */
public function assertDOSAllMatch($match, $dataObjectSet) { public function assertDOSAllMatch($match, $dataObjectSet) {
$extracted = array(); $extracted = array();
@ -692,12 +692,12 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
foreach($extracted as $i => $item) { foreach($extracted as $i => $item) {
$this->assertTrue( $this->assertTrue(
$this->dataObjectArrayMatch($item, $match), $this->dataObjectArrayMatch($item, $match),
"Failed asserting that the the following item matched " "Failed asserting that the the following item matched "
. var_export($match, true) . ": " . var_export($item, true) . var_export($match, true) . ": " . var_export($item, true)
); );
} }
} }
/** /**
* Helper function for the DOS matchers * Helper function for the DOS matchers
*/ */
@ -723,17 +723,17 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
public static function using_temp_db() { public static function using_temp_db() {
$dbConn = DB::getConn(); $dbConn = DB::getConn();
$prefix = defined('SS_DATABASE_PREFIX') ? SS_DATABASE_PREFIX : 'ss_'; $prefix = defined('SS_DATABASE_PREFIX') ? SS_DATABASE_PREFIX : 'ss_';
return $dbConn && (substr($dbConn->currentDatabase(), 0, strlen($prefix) + 5) return $dbConn && (substr($dbConn->currentDatabase(), 0, strlen($prefix) + 5)
== strtolower(sprintf('%stmpdb', $prefix))); == strtolower(sprintf('%stmpdb', $prefix)));
} }
public static function kill_temp_db() { public static function kill_temp_db() {
// Delete our temporary database // Delete our temporary database
if(self::using_temp_db()) { if(self::using_temp_db()) {
$dbConn = DB::getConn(); $dbConn = DB::getConn();
$dbName = $dbConn->currentDatabase(); $dbName = $dbConn->currentDatabase();
if($dbName && DB::getConn()->databaseExists($dbName)) { if($dbName && DB::getConn()->databaseExists($dbName)) {
// Some DataExtensions keep a static cache of information that needs to // Some DataExtensions keep a static cache of information that needs to
// be reset whenever the database is killed // be reset whenever the database is killed
foreach(ClassInfo::subclassesFor('DataExtension') as $class) { foreach(ClassInfo::subclassesFor('DataExtension') as $class) {
$toCall = array($class, 'on_db_reset'); $toCall = array($class, 'on_db_reset');
@ -745,7 +745,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
} }
} }
} }
/** /**
* Remove all content from the temporary database. * Remove all content from the temporary database.
*/ */
@ -753,8 +753,8 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
if(self::using_temp_db()) { if(self::using_temp_db()) {
$dbadmin = new DatabaseAdmin(); $dbadmin = new DatabaseAdmin();
$dbadmin->clearAllData(); $dbadmin->clearAllData();
// Some DataExtensions keep a static cache of information that needs to // Some DataExtensions keep a static cache of information that needs to
// be reset whenever the database is cleaned out // be reset whenever the database is cleaned out
$classes = array_merge(ClassInfo::subclassesFor('DataExtension'), ClassInfo::subclassesFor('DataObject')); $classes = array_merge(ClassInfo::subclassesFor('DataExtension'), ClassInfo::subclassesFor('DataObject'));
foreach($classes as $class) { foreach($classes as $class) {
@ -763,7 +763,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
} }
} }
} }
public static function create_temp_db() { public static function create_temp_db() {
// Disable PHPUnit error handling // Disable PHPUnit error handling
restore_error_handler(); restore_error_handler();
@ -784,13 +784,13 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
$st = Injector::inst()->create('SapphireTest'); $st = Injector::inst()->create('SapphireTest');
$st->resetDBSchema(); $st->resetDBSchema();
// Reinstate PHPUnit error handling // Reinstate PHPUnit error handling
set_error_handler(array('PHPUnit_Util_ErrorHandler', 'handleError')); set_error_handler(array('PHPUnit_Util_ErrorHandler', 'handleError'));
return $dbname; return $dbname;
} }
public static function delete_all_temp_dbs() { public static function delete_all_temp_dbs() {
$prefix = defined('SS_DATABASE_PREFIX') ? SS_DATABASE_PREFIX : 'ss_'; $prefix = defined('SS_DATABASE_PREFIX') ? SS_DATABASE_PREFIX : 'ss_';
foreach(DB::getConn()->allDatabaseNames() as $dbName) { foreach(DB::getConn()->allDatabaseNames() as $dbName) {
@ -805,7 +805,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
} }
} }
} }
/** /**
* Reset the testing database's schema. * Reset the testing database's schema.
* @param $includeExtraDataObjects If true, the extraDataObjects tables will also be included * @param $includeExtraDataObjects If true, the extraDataObjects tables will also be included
@ -846,7 +846,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
singleton('DataObject')->flushCache(); singleton('DataObject')->flushCache();
} }
} }
/** /**
* Create a member and group with the given permission code, and log in with it. * Create a member and group with the given permission code, and log in with it.
* Returns the member ID. * Returns the member ID.
@ -861,23 +861,23 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
$permission->Code = $permCode; $permission->Code = $permCode;
$permission->write(); $permission->write();
$group->Permissions()->add($permission); $group->Permissions()->add($permission);
$member = DataObject::get_one('Member', sprintf('"Email" = \'%s\'', "$permCode@example.org")); $member = DataObject::get_one('Member', sprintf('"Email" = \'%s\'', "$permCode@example.org"));
if(!$member) $member = Injector::inst()->create('Member'); if(!$member) $member = Injector::inst()->create('Member');
$member->FirstName = $permCode; $member->FirstName = $permCode;
$member->Surname = "User"; $member->Surname = "User";
$member->Email = "$permCode@example.org"; $member->Email = "$permCode@example.org";
$member->write(); $member->write();
$group->Members()->add($member); $group->Members()->add($member);
$this->cache_generatedMembers[$permCode] = $member; $this->cache_generatedMembers[$permCode] = $member;
} }
$this->cache_generatedMembers[$permCode]->logIn(); $this->cache_generatedMembers[$permCode]->logIn();
return $this->cache_generatedMembers[$permCode]->ID; return $this->cache_generatedMembers[$permCode]->ID;
} }
/** /**
* Cache for logInWithPermission() * Cache for logInWithPermission()
*/ */

View File

@ -182,18 +182,10 @@ end of each test.
$page->publish('Stage', 'Live'); $page->publish('Stage', 'Live');
} }
// reset configuration for the test. // set custom configuration for the test.
Config::nest();
Config::inst()->update('Foo', 'bar', 'Hello!'); Config::inst()->update('Foo', 'bar', 'Hello!');
} }
public function tearDown() {
// restores the config variables
Config::unnest();
parent::tearDown();
}
public function testMyMethod() { public function testMyMethod() {
// .. // ..
} }
@ -223,6 +215,32 @@ individual test case.
// .. // ..
} }
} }
### Config and Injector Nesting
A powerful feature of both [`Config`](/developer_guides/configuration/configuration/) and [`Injector`](/developer_guides/extending/injector/) is the ability to "nest" them so that you can make changes that can easily be discarded without having to manage previous values.
The testing suite makes use of this to "sandbox" each of the unit tests as well as each suite to prevent leakage between tests.
If you need to make changes to `Config` (or `Injector) for each test (or the whole suite) you can safely update `Config` (or `Injector`) settings in the `setUp` or `tearDown` functions.
It's important to remember that the `parent::setUp();` functions will need to be called first to ensure the nesting feature works as expected.
:::php
function setUpOnce() {
parent::setUpOnce();
//this will remain for the whole suite and be removed for any other tests
Config::inst()->update('ClassName', 'var_name', 'var_value');
}
function testFeatureDoesAsExpected() {
//this will be reset to 'var_value' at the end of this test function
Config::inst()->update('ClassName', 'var_name', 'new_var_value');
}
function testAnotherFeatureDoesAsExpected() {
Config::inst()->get('ClassName', 'var_name'); // this will be 'var_value'
}
## Generating a Coverage Report ## Generating a Coverage Report
@ -266,4 +284,4 @@ some `thirdparty/` directories add the following to the `phpunit.xml` configurat
* [api:TestRunner] * [api:TestRunner]
* [api:SapphireTest] * [api:SapphireTest]
* [api:FunctionalTest] * [api:FunctionalTest]

View File

@ -2,7 +2,7 @@
/** /**
* @package framework * @package framework
* @subpackage tests * @subpackage tests
* *
* @todo test Director::alternateBaseFolder() * @todo test Director::alternateBaseFolder()
*/ */
class DirectorTest extends SapphireTest { class DirectorTest extends SapphireTest {
@ -10,27 +10,24 @@ class DirectorTest extends SapphireTest {
protected static $originalRequestURI; protected static $originalRequestURI;
protected $originalProtocolHeaders = array(); protected $originalProtocolHeaders = array();
protected $originalGet = array(); protected $originalGet = array();
protected $originalSession = array(); protected $originalSession = array();
public function setUp() { public function setUp() {
parent::setUp(); parent::setUp();
// Required for testRequestFilterInDirectorTest
Injector::nest();
// Hold the original request URI once so it doesn't get overwritten // Hold the original request URI once so it doesn't get overwritten
if(!self::$originalRequestURI) { if(!self::$originalRequestURI) {
self::$originalRequestURI = $_SERVER['REQUEST_URI']; self::$originalRequestURI = $_SERVER['REQUEST_URI'];
} }
$_SERVER['REQUEST_URI'] = 'http://www.mysite.com'; $_SERVER['REQUEST_URI'] = 'http://www.mysite.com';
$this->originalGet = $_GET; $this->originalGet = $_GET;
$this->originalSession = $_SESSION; $this->originalSession = $_SESSION;
$_SESSION = array(); $_SESSION = array();
Config::inst()->update('Director', 'rules', array( Config::inst()->update('Director', 'rules', array(
'DirectorTestRule/$Action/$ID/$OtherID' => 'DirectorTestRequest_Controller', 'DirectorTestRule/$Action/$ID/$OtherID' => 'DirectorTestRequest_Controller',
'en-nz/$Action/$ID/$OtherID' => array( 'en-nz/$Action/$ID/$OtherID' => array(
@ -49,16 +46,13 @@ class DirectorTest extends SapphireTest {
} }
} }
} }
public function tearDown() { public function tearDown() {
// TODO Remove director rule, currently API doesnt allow this // TODO Remove director rule, currently API doesnt allow this
// Remove base URL override (setting to false reverts to default behaviour)
Config::inst()->update('Director', 'alternate_base_url', false);
$_GET = $this->originalGet; $_GET = $this->originalGet;
$_SESSION = $this->originalSession; $_SESSION = $this->originalSession;
// Reinstate the original REQUEST_URI after it was modified by some tests // Reinstate the original REQUEST_URI after it was modified by some tests
$_SERVER['REQUEST_URI'] = self::$originalRequestURI; $_SERVER['REQUEST_URI'] = self::$originalRequestURI;
@ -67,34 +61,32 @@ class DirectorTest extends SapphireTest {
$_SERVER[$header] = $value; $_SERVER[$header] = $value;
} }
} }
Injector::unnest();
parent::tearDown(); parent::tearDown();
} }
public function testFileExists() { public function testFileExists() {
$tempFileName = 'DirectorTest_testFileExists.tmp'; $tempFileName = 'DirectorTest_testFileExists.tmp';
$tempFilePath = TEMP_FOLDER . '/' . $tempFileName; $tempFilePath = TEMP_FOLDER . '/' . $tempFileName;
// create temp file // create temp file
file_put_contents($tempFilePath, ''); file_put_contents($tempFilePath, '');
$this->assertTrue( $this->assertTrue(
Director::fileExists($tempFilePath), Director::fileExists($tempFilePath),
'File exist check with absolute path' 'File exist check with absolute path'
); );
$this->assertTrue( $this->assertTrue(
Director::fileExists($tempFilePath . '?queryparams=1&foo[bar]=bar'), Director::fileExists($tempFilePath . '?queryparams=1&foo[bar]=bar'),
'File exist check with query params ignored' 'File exist check with query params ignored'
); );
unlink($tempFilePath); unlink($tempFilePath);
} }
public function testAbsoluteURL() { public function testAbsoluteURL() {
$rootURL = Director::protocolAndHost(); $rootURL = Director::protocolAndHost();
$_SERVER['REQUEST_URI'] = "$rootURL/mysite/sub-page/"; $_SERVER['REQUEST_URI'] = "$rootURL/mysite/sub-page/";
Config::inst()->update('Director', 'alternate_base_url', '/mysite/'); Config::inst()->update('Director', 'alternate_base_url', '/mysite/');
@ -116,20 +108,20 @@ class DirectorTest extends SapphireTest {
$this->assertEquals('http://www.mytest.com', Director::absoluteURL('http://www.mytest.com', true)); $this->assertEquals('http://www.mytest.com', Director::absoluteURL('http://www.mytest.com', true));
$this->assertEquals("$rootURL/test", Director::absoluteURL("$rootURL/test")); $this->assertEquals("$rootURL/test", Director::absoluteURL("$rootURL/test"));
$this->assertEquals("$rootURL/test", Director::absoluteURL("$rootURL/test", true)); $this->assertEquals("$rootURL/test", Director::absoluteURL("$rootURL/test", true));
// Test relative to base // Test relative to base
$this->assertEquals("$rootURL/mysite/test", Director::absoluteURL("test", true)); $this->assertEquals("$rootURL/mysite/test", Director::absoluteURL("test", true));
$this->assertEquals("$rootURL/mysite/test/url", Director::absoluteURL("test/url", true)); $this->assertEquals("$rootURL/mysite/test/url", Director::absoluteURL("test/url", true));
$this->assertEquals("$rootURL/root", Director::absoluteURL("/root", true)); $this->assertEquals("$rootURL/root", Director::absoluteURL("/root", true));
$this->assertEquals("$rootURL/root/url", Director::absoluteURL("/root/url", true)); $this->assertEquals("$rootURL/root/url", Director::absoluteURL("/root/url", true));
// Test relative to requested page // Test relative to requested page
$this->assertEquals("$rootURL/mysite/sub-page/test", Director::absoluteURL("test")); $this->assertEquals("$rootURL/mysite/sub-page/test", Director::absoluteURL("test"));
// Legacy behaviour resolves this to $rootURL/mysite/test/url // Legacy behaviour resolves this to $rootURL/mysite/test/url
//$this->assertEquals("$rootURL/mysite/sub-page/test/url", Director::absoluteURL("test/url")); //$this->assertEquals("$rootURL/mysite/sub-page/test/url", Director::absoluteURL("test/url"));
$this->assertEquals("$rootURL/root", Director::absoluteURL("/root")); $this->assertEquals("$rootURL/root", Director::absoluteURL("/root"));
$this->assertEquals("$rootURL/root/url", Director::absoluteURL("/root/url")); $this->assertEquals("$rootURL/root/url", Director::absoluteURL("/root/url"));
// Test that javascript links are not left intact // Test that javascript links are not left intact
$this->assertStringStartsNotWith('javascript', Director::absoluteURL('javascript:alert("attack")')); $this->assertStringStartsNotWith('javascript', Director::absoluteURL('javascript:alert("attack")'));
$this->assertStringStartsNotWith('alert', Director::absoluteURL('javascript:alert("attack")')); $this->assertStringStartsNotWith('alert', Director::absoluteURL('javascript:alert("attack")'));
@ -140,7 +132,7 @@ class DirectorTest extends SapphireTest {
public function testAlternativeBaseURL() { public function testAlternativeBaseURL() {
// Get original protocol and hostname // Get original protocol and hostname
$rootURL = Director::protocolAndHost(); $rootURL = Director::protocolAndHost();
// relative base URLs - you should end them in a / // relative base URLs - you should end them in a /
Config::inst()->update('Director', 'alternate_base_url', '/relativebase/'); Config::inst()->update('Director', 'alternate_base_url', '/relativebase/');
$_SERVER['REQUEST_URI'] = "$rootURL/relativebase/sub-page/"; $_SERVER['REQUEST_URI'] = "$rootURL/relativebase/sub-page/";
@ -180,7 +172,7 @@ class DirectorTest extends SapphireTest {
Director::absoluteURL('subfolder/test') Director::absoluteURL('subfolder/test')
); );
} }
/** /**
* Tests that {@link Director::is_absolute()} works under different environment types * Tests that {@link Director::is_absolute()} works under different environment types
*/ */
@ -196,12 +188,12 @@ class DirectorTest extends SapphireTest {
'folder' => false, 'folder' => false,
'a/c:/' => false 'a/c:/' => false
); );
foreach($expected as $path => $result) { foreach($expected as $path => $result) {
$this->assertEquals(Director::is_absolute($path), $result, "Test result for $path"); $this->assertEquals(Director::is_absolute($path), $result, "Test result for $path");
} }
} }
public function testIsAbsoluteUrl() { public function testIsAbsoluteUrl() {
$this->assertTrue(Director::is_absolute_url('http://test.com/testpage')); $this->assertTrue(Director::is_absolute_url('http://test.com/testpage'));
$this->assertTrue(Director::is_absolute_url('ftp://test.com')); $this->assertTrue(Director::is_absolute_url('ftp://test.com'));
@ -218,7 +210,7 @@ class DirectorTest extends SapphireTest {
$this->assertTrue(Director::is_absolute_url('http:test.com')); $this->assertTrue(Director::is_absolute_url('http:test.com'));
$this->assertTrue(Director::is_absolute_url('//http://test.com')); $this->assertTrue(Director::is_absolute_url('//http://test.com'));
} }
public function testIsRelativeUrl() { public function testIsRelativeUrl() {
$siteUrl = Director::absoluteBaseURL(); $siteUrl = Director::absoluteBaseURL();
$this->assertFalse(Director::is_relative_url('http://test.com')); $this->assertFalse(Director::is_relative_url('http://test.com'));
@ -231,18 +223,18 @@ class DirectorTest extends SapphireTest {
$this->assertTrue(Director::is_relative_url('/relative/?url=http://test.com')); $this->assertTrue(Director::is_relative_url('/relative/?url=http://test.com'));
$this->assertTrue(Director::is_relative_url('/relative/#=http://test.com')); $this->assertTrue(Director::is_relative_url('/relative/#=http://test.com'));
} }
public function testMakeRelative() { public function testMakeRelative() {
$siteUrl = Director::absoluteBaseURL(); $siteUrl = Director::absoluteBaseURL();
$siteUrlNoProtocol = preg_replace('/https?:\/\//', '', $siteUrl); $siteUrlNoProtocol = preg_replace('/https?:\/\//', '', $siteUrl);
$this->assertEquals(Director::makeRelative("$siteUrl"), ''); $this->assertEquals(Director::makeRelative("$siteUrl"), '');
$this->assertEquals(Director::makeRelative("https://$siteUrlNoProtocol"), ''); $this->assertEquals(Director::makeRelative("https://$siteUrlNoProtocol"), '');
$this->assertEquals(Director::makeRelative("http://$siteUrlNoProtocol"), ''); $this->assertEquals(Director::makeRelative("http://$siteUrlNoProtocol"), '');
$this->assertEquals(Director::makeRelative(" $siteUrl/testpage "), 'testpage'); $this->assertEquals(Director::makeRelative(" $siteUrl/testpage "), 'testpage');
$this->assertEquals(Director::makeRelative("$siteUrlNoProtocol/testpage"), 'testpage'); $this->assertEquals(Director::makeRelative("$siteUrlNoProtocol/testpage"), 'testpage');
$this->assertEquals(Director::makeRelative('ftp://test.com'), 'ftp://test.com'); $this->assertEquals(Director::makeRelative('ftp://test.com'), 'ftp://test.com');
$this->assertEquals(Director::makeRelative('http://test.com'), 'http://test.com'); $this->assertEquals(Director::makeRelative('http://test.com'), 'http://test.com');
@ -252,7 +244,7 @@ class DirectorTest extends SapphireTest {
$this->assertEquals("test", Director::makeRelative("https://".$siteUrlNoProtocol."/test")); $this->assertEquals("test", Director::makeRelative("https://".$siteUrlNoProtocol."/test"));
$this->assertEquals("test", Director::makeRelative("http://".$siteUrlNoProtocol."/test")); $this->assertEquals("test", Director::makeRelative("http://".$siteUrlNoProtocol."/test"));
} }
/** /**
* Mostly tested by {@link testIsRelativeUrl()}, * Mostly tested by {@link testIsRelativeUrl()},
* just adding the host name matching aspect here. * just adding the host name matching aspect here.
@ -264,7 +256,7 @@ class DirectorTest extends SapphireTest {
$this->assertFalse(Director::is_site_url("http://test.com?url=" . urlencode(Director::absoluteBaseURL()))); $this->assertFalse(Director::is_site_url("http://test.com?url=" . urlencode(Director::absoluteBaseURL())));
$this->assertFalse(Director::is_site_url("//test.com?url=" . Director::absoluteBaseURL())); $this->assertFalse(Director::is_site_url("//test.com?url=" . Director::absoluteBaseURL()));
} }
/** /**
* Tests isDev, isTest, isLive set from querystring * Tests isDev, isTest, isLive set from querystring
*/ */
@ -274,32 +266,32 @@ class DirectorTest extends SapphireTest {
unset($_SESSION['isLive']); unset($_SESSION['isLive']);
unset($_GET['isTest']); unset($_GET['isTest']);
unset($_GET['isDev']); unset($_GET['isDev']);
// Test isDev=1 // Test isDev=1
$_GET['isDev'] = '1'; $_GET['isDev'] = '1';
$this->assertTrue(Director::isDev()); $this->assertTrue(Director::isDev());
$this->assertFalse(Director::isTest()); $this->assertFalse(Director::isTest());
$this->assertFalse(Director::isLive()); $this->assertFalse(Director::isLive());
// Test persistence // Test persistence
unset($_GET['isDev']); unset($_GET['isDev']);
$this->assertTrue(Director::isDev()); $this->assertTrue(Director::isDev());
$this->assertFalse(Director::isTest()); $this->assertFalse(Director::isTest());
$this->assertFalse(Director::isLive()); $this->assertFalse(Director::isLive());
// Test change to isTest // Test change to isTest
$_GET['isTest'] = '1'; $_GET['isTest'] = '1';
$this->assertFalse(Director::isDev()); $this->assertFalse(Director::isDev());
$this->assertTrue(Director::isTest()); $this->assertTrue(Director::isTest());
$this->assertFalse(Director::isLive()); $this->assertFalse(Director::isLive());
// Test persistence // Test persistence
unset($_GET['isTest']); unset($_GET['isTest']);
$this->assertFalse(Director::isDev()); $this->assertFalse(Director::isDev());
$this->assertTrue(Director::isTest()); $this->assertTrue(Director::isTest());
$this->assertFalse(Director::isLive()); $this->assertFalse(Director::isLive());
} }
public function testResetGlobalsAfterTestRequest() { public function testResetGlobalsAfterTestRequest() {
$_GET = array('somekey' => 'getvalue'); $_GET = array('somekey' => 'getvalue');
$_POST = array('somekey' => 'postvalue'); $_POST = array('somekey' => 'postvalue');
@ -315,7 +307,7 @@ class DirectorTest extends SapphireTest {
$this->assertEquals('cookievalue', $_COOKIE['somekey'], $this->assertEquals('cookievalue', $_COOKIE['somekey'],
'$_COOKIE reset to original value after Director::test()'); '$_COOKIE reset to original value after Director::test()');
} }
public function testTestRequestCarriesGlobals() { public function testTestRequestCarriesGlobals() {
$fixture = array('somekey' => 'sometestvalue'); $fixture = array('somekey' => 'sometestvalue');
foreach(array('get', 'post') as $method) { foreach(array('get', 'post') as $method) {
@ -329,20 +321,20 @@ class DirectorTest extends SapphireTest {
} }
} }
} }
/** /**
* Tests that additional parameters specified in the routing table are * Tests that additional parameters specified in the routing table are
* saved in the request * saved in the request
*/ */
public function testRouteParams() { public function testRouteParams() {
Director::test('en-nz/myaction/myid/myotherid', null, null, null, null, null, null, $request); Director::test('en-nz/myaction/myid/myotherid', null, null, null, null, null, null, $request);
$this->assertEquals( $this->assertEquals(
$request->params(), $request->params(),
array( array(
'Controller' => 'DirectorTestRequest_Controller', 'Controller' => 'DirectorTestRequest_Controller',
'Action' => 'myaction', 'Action' => 'myaction',
'ID' => 'myid', 'ID' => 'myid',
'OtherID' => 'myotherid', 'OtherID' => 'myotherid',
'Locale' => 'en_NZ' 'Locale' => 'en_NZ'
) )
@ -406,7 +398,7 @@ class DirectorTest extends SapphireTest {
'CONTENT_TYPE' => 'text/xml', 'CONTENT_TYPE' => 'text/xml',
'CONTENT_LENGTH' => 10 'CONTENT_LENGTH' => 10
); );
$headers = array( $headers = array(
'Host' => 'host', 'Host' => 'host',
'User-Agent' => 'User Agent', 'User-Agent' => 'User Agent',
@ -416,7 +408,7 @@ class DirectorTest extends SapphireTest {
'Content-Type' => 'text/xml', 'Content-Type' => 'text/xml',
'Content-Length' => '10' 'Content-Length' => '10'
); );
$this->assertEquals($headers, Director::extract_request_headers($request)); $this->assertEquals($headers, Director::extract_request_headers($request));
} }
@ -483,34 +475,34 @@ class DirectorTest extends SapphireTest {
$_SERVER = $origServer; $_SERVER = $origServer;
} }
public function testRequestFilterInDirectorTest() { public function testRequestFilterInDirectorTest() {
$filter = new TestRequestFilter; $filter = new TestRequestFilter;
$processor = new RequestProcessor(array($filter)); $processor = new RequestProcessor(array($filter));
Injector::inst()->registerService($processor, 'RequestProcessor'); Injector::inst()->registerService($processor, 'RequestProcessor');
$response = Director::test('some-dummy-url'); $response = Director::test('some-dummy-url');
$this->assertEquals(1, $filter->preCalls); $this->assertEquals(1, $filter->preCalls);
$this->assertEquals(1, $filter->postCalls); $this->assertEquals(1, $filter->postCalls);
$filter->failPost = true; $filter->failPost = true;
$this->setExpectedException('SS_HTTPResponse_Exception'); $this->setExpectedException('SS_HTTPResponse_Exception');
$response = Director::test('some-dummy-url'); $response = Director::test('some-dummy-url');
$this->assertEquals(2, $filter->preCalls); $this->assertEquals(2, $filter->preCalls);
$this->assertEquals(2, $filter->postCalls); $this->assertEquals(2, $filter->postCalls);
$filter->failPre = true; $filter->failPre = true;
$response = Director::test('some-dummy-url'); $response = Director::test('some-dummy-url');
$this->assertEquals(3, $filter->preCalls); $this->assertEquals(3, $filter->preCalls);
// preCall 'false' will trigger an exception and prevent post call execution // preCall 'false' will trigger an exception and prevent post call execution
$this->assertEquals(2, $filter->postCalls); $this->assertEquals(2, $filter->postCalls);
} }
@ -519,13 +511,13 @@ class DirectorTest extends SapphireTest {
class TestRequestFilter implements RequestFilter, TestOnly { class TestRequestFilter implements RequestFilter, TestOnly {
public $preCalls = 0; public $preCalls = 0;
public $postCalls = 0; public $postCalls = 0;
public $failPre = false; public $failPre = false;
public $failPost = false; public $failPost = false;
public function preRequest(\SS_HTTPRequest $request, \Session $session, \DataModel $model) { public function preRequest(\SS_HTTPRequest $request, \Session $session, \DataModel $model) {
++$this->preCalls; ++$this->preCalls;
if ($this->failPre) { if ($this->failPre) {
return false; return false;
} }
@ -533,7 +525,7 @@ class TestRequestFilter implements RequestFilter, TestOnly {
public function postRequest(\SS_HTTPRequest $request, \SS_HTTPResponse $response, \DataModel $model) { public function postRequest(\SS_HTTPRequest $request, \SS_HTTPResponse $response, \DataModel $model) {
++$this->postCalls; ++$this->postCalls;
if ($this->failPost) { if ($this->failPost) {
return false; return false;
} }

View File

@ -82,23 +82,23 @@ class ConfigTest_TestNest extends Object implements TestOnly {
} }
class ConfigTest extends SapphireTest { class ConfigTest extends SapphireTest {
public function testNest() { public function testNest() {
// Check basic config // Check basic config
$this->assertEquals(3, Config::inst()->get('ConfigTest_TestNest', 'foo')); $this->assertEquals(3, Config::inst()->get('ConfigTest_TestNest', 'foo'));
$this->assertEquals(5, Config::inst()->get('ConfigTest_TestNest', 'bar')); $this->assertEquals(5, Config::inst()->get('ConfigTest_TestNest', 'bar'));
// Test nest copies data // Test nest copies data
Config::nest(); Config::nest();
$this->assertEquals(3, Config::inst()->get('ConfigTest_TestNest', 'foo')); $this->assertEquals(3, Config::inst()->get('ConfigTest_TestNest', 'foo'));
$this->assertEquals(5, Config::inst()->get('ConfigTest_TestNest', 'bar')); $this->assertEquals(5, Config::inst()->get('ConfigTest_TestNest', 'bar'));
// Test nested data can be updated // Test nested data can be updated
Config::inst()->update('ConfigTest_TestNest', 'foo', 4); Config::inst()->update('ConfigTest_TestNest', 'foo', 4);
$this->assertEquals(4, Config::inst()->get('ConfigTest_TestNest', 'foo')); $this->assertEquals(4, Config::inst()->get('ConfigTest_TestNest', 'foo'));
$this->assertEquals(5, Config::inst()->get('ConfigTest_TestNest', 'bar')); $this->assertEquals(5, Config::inst()->get('ConfigTest_TestNest', 'bar'));
// Test unnest restores data // Test unnest restores data
Config::unnest(); Config::unnest();
$this->assertEquals(3, Config::inst()->get('ConfigTest_TestNest', 'foo')); $this->assertEquals(3, Config::inst()->get('ConfigTest_TestNest', 'foo'));
@ -189,12 +189,11 @@ class ConfigTest extends SapphireTest {
// But it won't affect subclasses - this is *uninherited* static // But it won't affect subclasses - this is *uninherited* static
$this->assertNotContains('test_2b', $this->assertNotContains('test_2b',
Config::inst()->get('ConfigStaticTest_Third', 'first', Config::UNINHERITED)); Config::inst()->get('ConfigStaticTest_Third', 'first', Config::UNINHERITED));
$this->assertNotContains('test_2b', $this->assertNull(Config::inst()->get('ConfigStaticTest_Fourth', 'first', Config::UNINHERITED));
Config::inst()->get('ConfigStaticTest_Fourth', 'first', Config::UNINHERITED));
// Subclasses that don't have the static explicitly defined should allow definition, also // Subclasses that don't have the static explicitly defined should allow definition, also
// This also checks that set can be called after the first uninherited get() // This also checks that set can be called after the first uninherited get()
// call (which can be buggy due to caching) // call (which can be buggy due to caching)
Config::inst()->update('ConfigStaticTest_Fourth', 'first', array('test_4b')); Config::inst()->update('ConfigStaticTest_Fourth', 'first', array('test_4b'));
$this->assertContains('test_4b', Config::inst()->get('ConfigStaticTest_Fourth', 'first', Config::UNINHERITED)); $this->assertContains('test_4b', Config::inst()->get('ConfigStaticTest_Fourth', 'first', Config::UNINHERITED));
} }
@ -227,7 +226,7 @@ class ConfigTest extends SapphireTest {
$result = array('A' => 1, 'B' => 2, 'C' => array('Foo' => 1, 'Bar' => 2), 'D' => 3); $result = array('A' => 1, 'B' => 2, 'C' => array('Foo' => 1, 'Bar' => 2), 'D' => 3);
Config::merge_array_low_into_high($result, array('C' => array('Bar' => 3, 'Baz' => 4))); Config::merge_array_low_into_high($result, array('C' => array('Bar' => 3, 'Baz' => 4)));
$this->assertEquals($result, $this->assertEquals($result,
array('A' => 1, 'B' => 2, 'C' => array('Foo' => 1, 'Bar' => 2, 'Baz' => 4), 'D' => 3)); array('A' => 1, 'B' => 2, 'C' => array('Foo' => 1, 'Bar' => 2, 'Baz' => 4), 'D' => 3));
$result = array('A' => 1, 'B' => 2, 'C' => array('Foo' => 1, 'Bar' => 2), 'D' => 3); $result = array('A' => 1, 'B' => 2, 'C' => array('Foo' => 1, 'Bar' => 2), 'D' => 3);

View File

@ -391,7 +391,7 @@ class ConfigManifestTest extends SapphireTest {
public function testEnvironmentRules() { public function testEnvironmentRules() {
foreach (array('dev', 'test', 'live') as $env) { foreach (array('dev', 'test', 'live') as $env) {
Config::inst()->nest(); Config::nest();
Config::inst()->update('Director', 'environment_type', $env); Config::inst()->update('Director', 'environment_type', $env);
$config = $this->getConfigFixtureValue('Environment'); $config = $this->getConfigFixtureValue('Environment');
@ -403,13 +403,11 @@ class ConfigManifestTest extends SapphireTest {
); );
} }
Config::inst()->unnest(); Config::unnest();
} }
} }
public function testDynamicEnvironmentRules() { public function testDynamicEnvironmentRules() {
Config::inst()->nest();
// First, make sure environment_type is live // First, make sure environment_type is live
Config::inst()->update('Director', 'environment_type', 'live'); Config::inst()->update('Director', 'environment_type', 'live');
$this->assertEquals('live', Config::inst()->get('Director', 'environment_type')); $this->assertEquals('live', Config::inst()->get('Director', 'environment_type'));
@ -423,8 +421,6 @@ class ConfigManifestTest extends SapphireTest {
// And that the dynamic rule was calculated correctly // And that the dynamic rule was calculated correctly
$this->assertEquals('dev', Config::inst()->get('ConfigManifestTest', 'DynamicEnvironment')); $this->assertEquals('dev', Config::inst()->get('ConfigManifestTest', 'DynamicEnvironment'));
Config::inst()->unnest();
} }
public function testMultipleRules() { public function testMultipleRules() {

View File

@ -1,17 +1,17 @@
<?php <?php
/** /**
* Note: the running of this test is handled by the thing it's testing (DevelopmentAdmin controller). * Note: the running of this test is handled by the thing it's testing (DevelopmentAdmin controller).
* *
* @package framework * @package framework
* @package tests * @package tests
*/ */
class DevAdminControllerTest extends FunctionalTest { class DevAdminControllerTest extends FunctionalTest {
public function setUp(){ public function setUp(){
parent::setUp(); parent::setUp();
Config::nest()->update('DevelopmentAdmin', 'registered_controllers', array( Config::inst()->update('DevelopmentAdmin', 'registered_controllers', array(
'x1' => array( 'x1' => array(
'controller' => 'DevAdminControllerTest_Controller1', 'controller' => 'DevAdminControllerTest_Controller1',
'links' => array( 'links' => array(
@ -27,45 +27,40 @@ class DevAdminControllerTest extends FunctionalTest {
) )
)); ));
} }
public function tearDown(){
parent::tearDown();
Config::unnest();
}
public function testGoodRegisteredControllerOutput(){ public function testGoodRegisteredControllerOutput(){
// Check for the controller running from the registered url above // Check for the controller running from the registered url above
// (we use contains rather than equals because sometimes you get Warning: You probably want to define an entry in $_FILE_TO_URL_MAPPING) // (we use contains rather than equals because sometimes you get Warning: You probably want to define an entry in $_FILE_TO_URL_MAPPING)
$this->assertContains(DevAdminControllerTest_Controller1::OK_MSG, $this->getCapture('/dev/x1')); $this->assertContains(DevAdminControllerTest_Controller1::OK_MSG, $this->getCapture('/dev/x1'));
$this->assertContains(DevAdminControllerTest_Controller1::OK_MSG, $this->getCapture('/dev/x1/y1')); $this->assertContains(DevAdminControllerTest_Controller1::OK_MSG, $this->getCapture('/dev/x1/y1'));
} }
public function testGoodRegisteredControllerStatus(){ public function testGoodRegisteredControllerStatus(){
// Check response code is 200/OK // Check response code is 200/OK
$this->assertEquals(false, $this->getAndCheckForError('/dev/x1')); $this->assertEquals(false, $this->getAndCheckForError('/dev/x1'));
$this->assertEquals(false, $this->getAndCheckForError('/dev/x1/y1')); $this->assertEquals(false, $this->getAndCheckForError('/dev/x1/y1'));
// Check response code is 500/ some sort of error // Check response code is 500/ some sort of error
$this->assertEquals(true, $this->getAndCheckForError('/dev/x2')); $this->assertEquals(true, $this->getAndCheckForError('/dev/x2'));
} }
protected function getCapture($url){ protected function getCapture($url){
$this->logInWithPermission('ADMIN'); $this->logInWithPermission('ADMIN');
ob_start(); ob_start();
$this->get($url); $this->get($url);
$r = ob_get_contents(); $r = ob_get_contents();
ob_end_clean(); ob_end_clean();
return $r; return $r;
} }
protected function getAndCheckForError($url){ protected function getAndCheckForError($url){
$this->logInWithPermission('ADMIN'); $this->logInWithPermission('ADMIN');
if(Director::is_cli()){ if(Director::is_cli()){
// when in CLI the admin controller throws exceptions // when in CLI the admin controller throws exceptions
ob_start(); ob_start();
@ -75,10 +70,10 @@ class DevAdminControllerTest extends FunctionalTest {
ob_end_clean(); ob_end_clean();
return true; return true;
} }
ob_end_clean(); ob_end_clean();
return false; return false;
}else{ }else{
// when in http the admin controller sets a response header // when in http the admin controller sets a response header
ob_start(); ob_start();
@ -87,30 +82,30 @@ class DevAdminControllerTest extends FunctionalTest {
return $resp->isError(); return $resp->isError();
} }
} }
} }
class DevAdminControllerTest_Controller1 extends Controller { class DevAdminControllerTest_Controller1 extends Controller {
const OK_MSG = 'DevAdminControllerTest_Controller1 TEST OK'; const OK_MSG = 'DevAdminControllerTest_Controller1 TEST OK';
private static $url_handlers = array( private static $url_handlers = array(
'' => 'index', '' => 'index',
'y1' => 'y1Action' 'y1' => 'y1Action'
); );
private static $allowed_actions = array( private static $allowed_actions = array(
'index', 'index',
'y1Action', 'y1Action',
); );
public function index(){ public function index(){
echo self::OK_MSG; echo self::OK_MSG;
} }
public function y1Action(){ public function y1Action(){
echo self::OK_MSG; echo self::OK_MSG;
} }
} }

View File

@ -5,13 +5,13 @@ class DataObjectSchemaGenerationTest extends SapphireTest {
'DataObjectSchemaGenerationTest_DO', 'DataObjectSchemaGenerationTest_DO',
'DataObjectSchemaGenerationTest_IndexDO' 'DataObjectSchemaGenerationTest_IndexDO'
); );
public function setUpOnce() { public function setUpOnce() {
// enable fulltext option on this table // enable fulltext option on this table
Config::inst()->update('DataObjectSchemaGenerationTest_IndexDO', 'create_table_options', Config::inst()->update('DataObjectSchemaGenerationTest_IndexDO', 'create_table_options',
array('MySQLDatabase' => 'ENGINE=MyISAM')); array('MySQLDatabase' => 'ENGINE=MyISAM'));
parent::setUpOnce(); parent::setUpOnce();
} }
@ -23,7 +23,7 @@ class DataObjectSchemaGenerationTest extends SapphireTest {
DB::quiet(); DB::quiet();
// Table will have been initially created by the $extraDataObjects setting // Table will have been initially created by the $extraDataObjects setting
// Verify that it doesn't need to be recreated // Verify that it doesn't need to be recreated
$db->beginSchemaUpdate(); $db->beginSchemaUpdate();
$obj = new DataObjectSchemaGenerationTest_DO(); $obj = new DataObjectSchemaGenerationTest_DO();
@ -41,9 +41,8 @@ class DataObjectSchemaGenerationTest extends SapphireTest {
DB::quiet(); DB::quiet();
// Table will have been initially created by the $extraDataObjects setting // Table will have been initially created by the $extraDataObjects setting
// Let's insert a new field here // Let's insert a new field here
Config::nest();
Config::inst()->update('DataObjectSchemaGenerationTest_DO', 'db', array( Config::inst()->update('DataObjectSchemaGenerationTest_DO', 'db', array(
'SecretField' => 'Varchar(100)' 'SecretField' => 'Varchar(100)'
)); ));
@ -55,20 +54,17 @@ class DataObjectSchemaGenerationTest extends SapphireTest {
$needsUpdating = $db->doesSchemaNeedUpdating(); $needsUpdating = $db->doesSchemaNeedUpdating();
$db->cancelSchemaUpdate(); $db->cancelSchemaUpdate();
$this->assertTrue($needsUpdating); $this->assertTrue($needsUpdating);
// Restore db configuration
Config::unnest();
} }
/** /**
* Check that indexes on a newly generated class do not subsequently request modification * Check that indexes on a newly generated class do not subsequently request modification
*/ */
public function testIndexesDontRerequestChanges() { public function testIndexesDontRerequestChanges() {
$db = DB::getConn(); $db = DB::getConn();
DB::quiet(); DB::quiet();
// Table will have been initially created by the $extraDataObjects setting // Table will have been initially created by the $extraDataObjects setting
// Verify that it doesn't need to be recreated // Verify that it doesn't need to be recreated
$db->beginSchemaUpdate(); $db->beginSchemaUpdate();
$obj = new DataObjectSchemaGenerationTest_IndexDO(); $obj = new DataObjectSchemaGenerationTest_IndexDO();
@ -76,9 +72,8 @@ class DataObjectSchemaGenerationTest extends SapphireTest {
$needsUpdating = $db->doesSchemaNeedUpdating(); $needsUpdating = $db->doesSchemaNeedUpdating();
$db->cancelSchemaUpdate(); $db->cancelSchemaUpdate();
$this->assertFalse($needsUpdating); $this->assertFalse($needsUpdating);
// Test with alternate index format, although these indexes are the same // Test with alternate index format, although these indexes are the same
Config::nest();
Config::inst()->remove('DataObjectSchemaGenerationTest_IndexDO', 'indexes'); Config::inst()->remove('DataObjectSchemaGenerationTest_IndexDO', 'indexes');
Config::inst()->update('DataObjectSchemaGenerationTest_IndexDO', 'indexes', Config::inst()->update('DataObjectSchemaGenerationTest_IndexDO', 'indexes',
Config::inst()->get('DataObjectSchemaGenerationTest_IndexDO', 'indexes_alt') Config::inst()->get('DataObjectSchemaGenerationTest_IndexDO', 'indexes_alt')
@ -91,22 +86,18 @@ class DataObjectSchemaGenerationTest extends SapphireTest {
$needsUpdating = $db->doesSchemaNeedUpdating(); $needsUpdating = $db->doesSchemaNeedUpdating();
$db->cancelSchemaUpdate(); $db->cancelSchemaUpdate();
$this->assertFalse($needsUpdating); $this->assertFalse($needsUpdating);
// Restore old index format
Config::unnest();
} }
/** /**
* Check that updates to a dataobject's indexes are reflected in DDL * Check that updates to a dataobject's indexes are reflected in DDL
*/ */
public function testIndexesRerequestChanges() { public function testIndexesRerequestChanges() {
$db = DB::getConn(); $db = DB::getConn();
DB::quiet(); DB::quiet();
// Table will have been initially created by the $extraDataObjects setting // Table will have been initially created by the $extraDataObjects setting
// Update the SearchFields index here // Update the SearchFields index here
Config::nest();
Config::inst()->update('DataObjectSchemaGenerationTest_IndexDO', 'indexes', array( Config::inst()->update('DataObjectSchemaGenerationTest_IndexDO', 'indexes', array(
'SearchFields' => array( 'SearchFields' => array(
'value' => 'Title' 'value' => 'Title'
@ -120,17 +111,14 @@ class DataObjectSchemaGenerationTest extends SapphireTest {
$needsUpdating = $db->doesSchemaNeedUpdating(); $needsUpdating = $db->doesSchemaNeedUpdating();
$db->cancelSchemaUpdate(); $db->cancelSchemaUpdate();
$this->assertTrue($needsUpdating); $this->assertTrue($needsUpdating);
// Restore old indexes
Config::unnest();
} }
/** /**
* Tests the generation of the ClassName spec and ensure it's not unnecessarily influenced * Tests the generation of the ClassName spec and ensure it's not unnecessarily influenced
* by the order of classnames of existing records * by the order of classnames of existing records
*/ */
public function testClassNameSpecGeneration() { public function testClassNameSpecGeneration() {
// Test with blank entries // Test with blank entries
DataObject::clear_classname_spec_cache(); DataObject::clear_classname_spec_cache();
$fields = DataObject::database_fields('DataObjectSchemaGenerationTest_DO'); $fields = DataObject::database_fields('DataObjectSchemaGenerationTest_DO');
@ -138,7 +126,7 @@ class DataObjectSchemaGenerationTest extends SapphireTest {
"Enum('DataObjectSchemaGenerationTest_DO, DataObjectSchemaGenerationTest_IndexDO')", "Enum('DataObjectSchemaGenerationTest_DO, DataObjectSchemaGenerationTest_IndexDO')",
$fields['ClassName'] $fields['ClassName']
); );
// Test with instance of subclass // Test with instance of subclass
$item1 = new DataObjectSchemaGenerationTest_IndexDO(); $item1 = new DataObjectSchemaGenerationTest_IndexDO();
$item1->write(); $item1->write();
@ -149,7 +137,7 @@ class DataObjectSchemaGenerationTest extends SapphireTest {
$fields['ClassName'] $fields['ClassName']
); );
$item1->delete(); $item1->delete();
// Test with instance of main class // Test with instance of main class
$item2 = new DataObjectSchemaGenerationTest_DO(); $item2 = new DataObjectSchemaGenerationTest_DO();
$item2->write(); $item2->write();
@ -160,7 +148,7 @@ class DataObjectSchemaGenerationTest extends SapphireTest {
$fields['ClassName'] $fields['ClassName']
); );
$item2->delete(); $item2->delete();
// Test with instances of both classes // Test with instances of both classes
$item1 = new DataObjectSchemaGenerationTest_IndexDO(); $item1 = new DataObjectSchemaGenerationTest_IndexDO();
$item1->write(); $item1->write();
@ -199,7 +187,7 @@ class DataObjectSchemaGenerationTest_IndexDO extends DataObjectSchemaGenerationT
'value' => '"Title","Content"' 'value' => '"Title","Content"'
) )
); );
/** @config */ /** @config */
private static $indexes_alt = array( private static $indexes_alt = array(
'NameIndex' => array( 'NameIndex' => array(
@ -209,4 +197,4 @@ class DataObjectSchemaGenerationTest_IndexDO extends DataObjectSchemaGenerationT
), ),
'SearchFields' => 'fulltext ("Title","Content")' 'SearchFields' => 'fulltext ("Title","Content")'
); );
} }

View File

@ -8,8 +8,9 @@ class MySQLDatabaseTest extends SapphireTest {
protected $extraDataObjects = array( protected $extraDataObjects = array(
'MySQLDatabaseTest_DO', 'MySQLDatabaseTest_DO',
); );
public function setUp() { public function setUp() {
parent::setUp();
if(DB::getConn() instanceof MySQLDatabase) { if(DB::getConn() instanceof MySQLDatabase) {
MySQLDatabaseTest_DO::config()->db = array( MySQLDatabaseTest_DO::config()->db = array(
'MultiEnum1' => 'MultiEnum("A, B, C, D","")', 'MultiEnum1' => 'MultiEnum("A, B, C, D","")',
@ -18,9 +19,8 @@ class MySQLDatabaseTest extends SapphireTest {
); );
} }
$this->markTestSkipped('This test requires the Config API to be immutable'); $this->markTestSkipped('This test requires the Config API to be immutable');
parent::setUp();
} }
/** /**
* Check that once a schema has been generated, then it doesn't need any more updating * Check that once a schema has been generated, then it doesn't need any more updating
*/ */

View File

@ -1,16 +1,6 @@
<?php <?php
class OembedTest extends SapphireTest { class OembedTest extends SapphireTest {
public function setUp() {
parent::setUp();
Config::nest();
}
public function tearDown() {
Config::unnest();
parent::tearDown();
}
public function testGetOembedFromUrl() { public function testGetOembedFromUrl() {
Config::inst()->update('Oembed', 'providers', array( Config::inst()->update('Oembed', 'providers', array(
'http://*.silverstripe.com/watch*'=>'http://www.silverstripe.com/oembed/' 'http://*.silverstripe.com/watch*'=>'http://www.silverstripe.com/oembed/'
@ -35,7 +25,7 @@ class OembedTest extends SapphireTest {
$result = Oembed::get_oembed_from_url('http://www.silverstripe.com/watch12345', false, array('foo'=>'bar')); $result = Oembed::get_oembed_from_url('http://www.silverstripe.com/watch12345', false, array('foo'=>'bar'));
$this->assertTrue($result!=false); $this->assertTrue($result!=false);
$this->assertEquals($result->getOembedURL(), 'http://www.silverstripe.com/oembed/?format=json&url=' $this->assertEquals($result->getOembedURL(), 'http://www.silverstripe.com/oembed/?format=json&url='
. urlencode('http://www.silverstripe.com/watch12345').'&foo=bar', . urlencode('http://www.silverstripe.com/watch12345').'&foo=bar',
'Includes options'); 'Includes options');
// Test magic. // Test magic.

View File

@ -14,46 +14,40 @@ class BasicAuthTest extends FunctionalTest {
parent::setUp(); parent::setUp();
// Fixtures assume Email is the field used to identify the log in identity // Fixtures assume Email is the field used to identify the log in identity
Config::nest();
Member::config()->unique_identifier_field = 'Email'; Member::config()->unique_identifier_field = 'Email';
Member::config()->lock_out_after_incorrect_logins = 10; Member::config()->lock_out_after_incorrect_logins = 10;
} }
public function tearDown() {
Config::unnest();
parent::tearDown();
}
public function testBasicAuthEnabledWithoutLogin() { public function testBasicAuthEnabledWithoutLogin() {
$origUser = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : null; $origUser = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : null;
$origPw = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : null; $origPw = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : null;
unset($_SERVER['PHP_AUTH_USER']); unset($_SERVER['PHP_AUTH_USER']);
unset($_SERVER['PHP_AUTH_PW']); unset($_SERVER['PHP_AUTH_PW']);
$response = Director::test('BasicAuthTest_ControllerSecuredWithPermission'); $response = Director::test('BasicAuthTest_ControllerSecuredWithPermission');
$this->assertEquals(401, $response->getStatusCode()); $this->assertEquals(401, $response->getStatusCode());
$_SERVER['PHP_AUTH_USER'] = $origUser; $_SERVER['PHP_AUTH_USER'] = $origUser;
$_SERVER['PHP_AUTH_PW'] = $origPw; $_SERVER['PHP_AUTH_PW'] = $origPw;
} }
public function testBasicAuthDoesntCallActionOrFurtherInitOnAuthFailure() { public function testBasicAuthDoesntCallActionOrFurtherInitOnAuthFailure() {
$origUser = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : null; $origUser = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : null;
$origPw = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : null; $origPw = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : null;
unset($_SERVER['PHP_AUTH_USER']); unset($_SERVER['PHP_AUTH_USER']);
unset($_SERVER['PHP_AUTH_PW']); unset($_SERVER['PHP_AUTH_PW']);
$response = Director::test('BasicAuthTest_ControllerSecuredWithPermission'); $response = Director::test('BasicAuthTest_ControllerSecuredWithPermission');
$this->assertFalse(BasicAuthTest_ControllerSecuredWithPermission::$index_called); $this->assertFalse(BasicAuthTest_ControllerSecuredWithPermission::$index_called);
$this->assertFalse(BasicAuthTest_ControllerSecuredWithPermission::$post_init_called); $this->assertFalse(BasicAuthTest_ControllerSecuredWithPermission::$post_init_called);
$_SERVER['PHP_AUTH_USER'] = 'user-in-mygroup@test.com'; $_SERVER['PHP_AUTH_USER'] = 'user-in-mygroup@test.com';
$_SERVER['PHP_AUTH_PW'] = 'test'; $_SERVER['PHP_AUTH_PW'] = 'test';
$response = Director::test('BasicAuthTest_ControllerSecuredWithPermission'); $response = Director::test('BasicAuthTest_ControllerSecuredWithPermission');
$this->assertTrue(BasicAuthTest_ControllerSecuredWithPermission::$index_called); $this->assertTrue(BasicAuthTest_ControllerSecuredWithPermission::$index_called);
$this->assertTrue(BasicAuthTest_ControllerSecuredWithPermission::$post_init_called); $this->assertTrue(BasicAuthTest_ControllerSecuredWithPermission::$post_init_called);
$_SERVER['PHP_AUTH_USER'] = $origUser; $_SERVER['PHP_AUTH_USER'] = $origUser;
$_SERVER['PHP_AUTH_PW'] = $origPw; $_SERVER['PHP_AUTH_PW'] = $origPw;
} }
@ -61,45 +55,45 @@ class BasicAuthTest extends FunctionalTest {
public function testBasicAuthEnabledWithPermission() { public function testBasicAuthEnabledWithPermission() {
$origUser = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : null; $origUser = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : null;
$origPw = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : null; $origPw = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : null;
$_SERVER['PHP_AUTH_USER'] = 'user-in-mygroup@test.com'; $_SERVER['PHP_AUTH_USER'] = 'user-in-mygroup@test.com';
$_SERVER['PHP_AUTH_PW'] = 'wrongpassword'; $_SERVER['PHP_AUTH_PW'] = 'wrongpassword';
$response = Director::test('BasicAuthTest_ControllerSecuredWithPermission'); $response = Director::test('BasicAuthTest_ControllerSecuredWithPermission');
$this->assertEquals(401, $response->getStatusCode(), 'Invalid users dont have access'); $this->assertEquals(401, $response->getStatusCode(), 'Invalid users dont have access');
$_SERVER['PHP_AUTH_USER'] = 'user-without-groups@test.com'; $_SERVER['PHP_AUTH_USER'] = 'user-without-groups@test.com';
$_SERVER['PHP_AUTH_PW'] = 'test'; $_SERVER['PHP_AUTH_PW'] = 'test';
$response = Director::test('BasicAuthTest_ControllerSecuredWithPermission'); $response = Director::test('BasicAuthTest_ControllerSecuredWithPermission');
$this->assertEquals(401, $response->getStatusCode(), 'Valid user without required permission has no access'); $this->assertEquals(401, $response->getStatusCode(), 'Valid user without required permission has no access');
$_SERVER['PHP_AUTH_USER'] = 'user-in-mygroup@test.com'; $_SERVER['PHP_AUTH_USER'] = 'user-in-mygroup@test.com';
$_SERVER['PHP_AUTH_PW'] = 'test'; $_SERVER['PHP_AUTH_PW'] = 'test';
$response = Director::test('BasicAuthTest_ControllerSecuredWithPermission'); $response = Director::test('BasicAuthTest_ControllerSecuredWithPermission');
$this->assertEquals(200, $response->getStatusCode(), 'Valid user with required permission has access'); $this->assertEquals(200, $response->getStatusCode(), 'Valid user with required permission has access');
$_SERVER['PHP_AUTH_USER'] = $origUser; $_SERVER['PHP_AUTH_USER'] = $origUser;
$_SERVER['PHP_AUTH_PW'] = $origPw; $_SERVER['PHP_AUTH_PW'] = $origPw;
} }
public function testBasicAuthEnabledWithoutPermission() { public function testBasicAuthEnabledWithoutPermission() {
$origUser = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : null; $origUser = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : null;
$origPw = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : null; $origPw = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : null;
$_SERVER['PHP_AUTH_USER'] = 'user-without-groups@test.com'; $_SERVER['PHP_AUTH_USER'] = 'user-without-groups@test.com';
$_SERVER['PHP_AUTH_PW'] = 'wrongpassword'; $_SERVER['PHP_AUTH_PW'] = 'wrongpassword';
$response = Director::test('BasicAuthTest_ControllerSecuredWithoutPermission'); $response = Director::test('BasicAuthTest_ControllerSecuredWithoutPermission');
$this->assertEquals(401, $response->getStatusCode(), 'Invalid users dont have access'); $this->assertEquals(401, $response->getStatusCode(), 'Invalid users dont have access');
$_SERVER['PHP_AUTH_USER'] = 'user-without-groups@test.com'; $_SERVER['PHP_AUTH_USER'] = 'user-without-groups@test.com';
$_SERVER['PHP_AUTH_PW'] = 'test'; $_SERVER['PHP_AUTH_PW'] = 'test';
$response = Director::test('BasicAuthTest_ControllerSecuredWithoutPermission'); $response = Director::test('BasicAuthTest_ControllerSecuredWithoutPermission');
$this->assertEquals(200, $response->getStatusCode(), 'All valid users have access'); $this->assertEquals(200, $response->getStatusCode(), 'All valid users have access');
$_SERVER['PHP_AUTH_USER'] = 'user-in-mygroup@test.com'; $_SERVER['PHP_AUTH_USER'] = 'user-in-mygroup@test.com';
$_SERVER['PHP_AUTH_PW'] = 'test'; $_SERVER['PHP_AUTH_PW'] = 'test';
$response = Director::test('BasicAuthTest_ControllerSecuredWithoutPermission'); $response = Director::test('BasicAuthTest_ControllerSecuredWithoutPermission');
$this->assertEquals(200, $response->getStatusCode(), 'All valid users have access'); $this->assertEquals(200, $response->getStatusCode(), 'All valid users have access');
$_SERVER['PHP_AUTH_USER'] = $origUser; $_SERVER['PHP_AUTH_USER'] = $origUser;
$_SERVER['PHP_AUTH_PW'] = $origPw; $_SERVER['PHP_AUTH_PW'] = $origPw;
} }
@ -131,23 +125,23 @@ class BasicAuthTest extends FunctionalTest {
} }
class BasicAuthTest_ControllerSecuredWithPermission extends Controller implements TestOnly { class BasicAuthTest_ControllerSecuredWithPermission extends Controller implements TestOnly {
static $post_init_called = false; static $post_init_called = false;
static $index_called = false; static $index_called = false;
protected $template = 'BlankPage'; protected $template = 'BlankPage';
public function init() { public function init() {
self::$post_init_called = false; self::$post_init_called = false;
self::$index_called = false; self::$index_called = false;
BasicAuth::protect_entire_site(true, 'MYCODE'); BasicAuth::protect_entire_site(true, 'MYCODE');
parent::init(); parent::init();
self::$post_init_called = true; self::$post_init_called = true;
} }
public function index() { public function index() {
self::$index_called = true; self::$index_called = true;
} }
@ -164,5 +158,5 @@ class BasicAuthTest_ControllerSecuredWithoutPermission extends Controller implem
BasicAuth::protect_entire_site(true, null); BasicAuth::protect_entire_site(true, null);
parent::init(); parent::init();
} }
} }