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.
* Sapphire unit testing is based on PHPUnit, but provides a number of hooks into our data model that make it easier
* to work with.
*
*
* @package framework
* @subpackage testing
*/
class SapphireTest extends PHPUnit_Framework_TestCase {
/** @config */
private static $dependencies = array(
'fixtureFactory' => '%$FixtureFactory',
@ -21,7 +21,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
* If passed as an array, multiple fixture files will be loaded.
* Please note that you won't be able to refer with "=>" notation
* between the fixtures, they act independent of each other.
*
*
* @var string|array
*/
protected static $fixture_file = null;
@ -30,19 +30,19 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
* @var FixtureFactory
*/
protected $fixtureFactory;
/**
* @var bool Set whether to include this test in the TestRunner or to skip this.
*/
protected $skipTest = false;
/**
* @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.
*/
protected $usesDatabase = null;
protected $originalMailer;
protected $originalMemberPasswordValidator;
protected $originalRequirements;
@ -50,33 +50,33 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
protected $originalTheme;
protected $originalNestedURLsState;
protected $originalMemoryLimit;
protected $mailer;
/**
* Pointer to the manifest that isn't a test manifest
*/
protected static $regular_manifest;
/**
* @var boolean
*/
protected static $is_running_test = false;
protected static $test_class_manifest;
/**
* By default, setUp() does not require default records. Pass
* class names in here, and the require/augment default records
* function will be called on them.
*/
protected $requireDefaultRecordsFrom = array();
/**
* 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.
*
*
* 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.
*/
@ -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
* 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
* of required extensions on that class.
*
*
* Example:
* <code>
* array("MyTreeDataObject" => array("Versioned", "Hierarchy"))
@ -97,35 +97,35 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
*/
protected $requiredExtensions = array(
);
/**
* 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.
* Set it to an array of DataObject subclass names.
*/
protected $extraDataObjects = array();
/**
* We need to disabling backing up of globals to avoid overriding
* the few globals SilverStripe relies on, like $lang for the i18n subsystem.
*
*
* @see http://sebastian-bergmann.de/archives/797-Global-Variables-and-PHPUnit.html
*/
protected $backupGlobals = FALSE;
/**
/**
* Helper arrays for illegalExtensions/requiredExtensions code
*/
private $extensionsToReapply = array(), $extensionsToRemove = array();
/**
* Determines if unit tests are currently run (via {@link TestRunner}).
* This is used as a cheap replacement for fully mockable state
* in certain contiditions (e.g. access checks).
* Caution: When set to FALSE, certain controllers might bypass
* access checks, so this is a very security sensitive setting.
*
*
* @return boolean
*/
public static function is_running_test() {
@ -133,7 +133,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
}
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
* @deprecated 3.1 Use $fixtureFactory instad
*/
protected $fixtures = array();
protected $fixtures = array();
protected $model;
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.
if(get_class($this) == "SapphireTest") $this->skipTest = true;
if($this->skipTest) {
$this->markTestSkipped(sprintf(
'Skipping %s ', get_class($this)
));
return;
}
// Mark test as being run
$this->originalIsRunningTest = self::$is_running_test;
self::$is_running_test = true;
@ -185,16 +190,16 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
i18n::set_locale(i18n::default_locale());
i18n::config()->date_format = null;
i18n::config()->time_format = null;
// Set default timezone consistently to avoid NZ-specific dependencies
date_default_timezone_set('UTC');
// Remove password validation
$this->originalMemberPasswordValidator = Member::password_validator();
$this->originalRequirements = Requirements::backend();
Member::set_password_validator(null);
Config::inst()->update('Cookie', 'report_errors', false);
if(class_exists('RootURLController')) RootURLController::reset();
if(class_exists('Translatable')) Translatable::reset();
Versioned::reset();
@ -203,7 +208,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
Hierarchy::reset();
if(Controller::has_curr()) Controller::curr()->setSession(Injector::inst()->create('Session', array()));
Security::$database_is_ready = null;
$fixtureFile = static::get_fixture_file();
$prefix = defined('SS_DATABASE_PREFIX') ? SS_DATABASE_PREFIX : 'ss_';
@ -213,13 +218,13 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
$this->mailer = new TestMailer();
Email::set_mailer($this->mailer);
Config::inst()->remove('Email', 'send_all_emails_to');
// Todo: this could be a special test model
$this->model = DataModel::inst();
// Set up fixture
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))) {
//echo "Re-creating temp database... ";
@ -228,9 +233,9 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
}
singleton('DataObject')->flushCache();
self::empty_temp_db();
foreach($this->requireDefaultRecordsFrom as $className) {
$instance = singleton($className);
if (method_exists($instance, 'requireDefaultRecords')) $instance->requireDefaultRecords();
@ -245,14 +250,14 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
foreach($fixtureFiles as $fixtureFilePath) {
// Support fixture paths relative to the test class, rather than relative to webroot
// String checking is faster than file_exists() calls.
$isRelativeToFile = (strpos('/', $fixtureFilePath) === false
$isRelativeToFile = (strpos('/', $fixtureFilePath) === false
|| preg_match('/^\.\./', $fixtureFilePath));
if($isRelativeToFile) {
$resolvedPath = realpath($pathForClass . '/' . $fixtureFilePath);
if($resolvedPath) $fixtureFilePath = $resolvedPath;
}
$fixture = Injector::inst()->create('YamlFixture', $fixtureFilePath);
$fixture->writeInto($this->getFixtureFactory());
$this->fixtures[] = $fixture;
@ -262,20 +267,20 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
$i++;
}
}
$this->logInWithPermission("ADMIN");
}
// Preserve memory settings
$this->originalMemoryLimit = ini_get('memory_limit');
// turn off template debugging
Config::inst()->update('SSViewer', 'source_file_comments', false);
// Clear requirements
Requirements::clear();
}
/**
* Called once per test case ({@link SapphireTest} subclass).
* 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.
*/
public function setUpOnce() {
//nest config and injector for each suite so they are effectively sandboxed
Config::nest();
Injector::nest();
$isAltered = false;
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($isAltered || $this->extensionsToReapply || $this->extensionsToRemove || $this->extraDataObjects) {
if(!self::using_temp_db()) self::create_temp_db();
$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()
Injector::inst()->unregisterAllObjects();
// Set default timezone consistently to avoid NZ-specific dependencies
date_default_timezone_set('UTC');
}
/**
* tearDown method that's called once per test class rather once per test method.
*/
public function tearDownOnce() {
// If we have made changes to the extensions present, then migrate the database schema.
if($this->extensionsToReapply || $this->extensionsToRemove) {
// Remove extensions added for testing
foreach($this->extensionsToRemove as $class => $extensions) {
foreach($extensions as $extension) {
$class::remove_extension($extension);
}
}
//unnest injector / config now that the test suite is over
// this will reset all the extensions on the object too (see setUpOnce)
Injector::unnest();
Config::unnest();
// Reapply ones removed
foreach($this->extensionsToReapply as $class => $extensions) {
foreach($extensions as $extension) {
$class::add_extension($extension);
}
}
}
if($this->extensionsToReapply || $this->extensionsToRemove || $this->extraDataObjects) {
if(!empty($this->extensionsToReapply) || !empty($this->extensionsToRemove) || !empty($this->extraDataObjects)) {
$this->resetDBSchema();
}
}
/**
* @return FixtureFactory
*/
@ -367,10 +364,10 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
$this->fixtureFactory = $factory;
return $this;
}
/**
* 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 $identifier The identifier string, as provided in your fixture file
* @return int
@ -416,12 +413,12 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
"Couldn't find object '%s' (class: %s)",
$identifier,
$className
), E_USER_ERROR);
), E_USER_ERROR);
}
return $obj;
}
/**
* Load a YAML fixture file into the database.
* 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());
$this->fixtures[] = $fixture;
}
/**
* Clear all fixtures which were previously loaded through
* {@link loadFixture()}
* {@link loadFixture()}
*/
public function clearFixtures() {
$this->fixtures = array();
$this->getFixtureFactory()->clear();
}
/**
* Useful for writing unit tests without hardcoding folder structures.
*
*
* @return String Absolute path to current class.
*/
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));
return dirname($filename);
}
/**
* @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)));
return $path;
}
public function tearDown() {
// Preserve memory settings
ini_set('memory_limit', ($this->originalMemoryLimit) ? $this->originalMemoryLimit : -1);
@ -474,16 +471,16 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
Email::set_mailer($this->originalMailer);
$this->originalMailer = null;
}
$this->mailer = null;
$this->mailer = null;
// Restore password validation
if($this->originalMemberPasswordValidator) {
Member::set_password_validator($this->originalMemberPasswordValidator);
Member::set_password_validator($this->originalMemberPasswordValidator);
}
// Restore requirements
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
@ -492,15 +489,18 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
// Reset mocked datetime
SS_Datetime::clear_mock_now();
// 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.
$controller = Controller::has_curr() ? Controller::curr() : null;
if ( $controller && $controller->response && $controller->response->getHeader('Location') ) {
$controller->response->setStatusCode(200);
$controller->response->removeHeader('Location');
}
//unnest injector / config now that tests are over
Injector::unnest();
Config::unnest();
}
public static function assertContains(
@ -547,7 +547,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
public function findEmail($to, $from = null, $subject = null, $content = null) {
return $this->mailer->findEmail($to, $from, $subject, $content);
}
/**
* 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.
@ -579,7 +579,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
/**
* Assert that the given {@link SS_List} includes DataObjects matching the given 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
* either pass a single pattern or an array of patterns.
* @param $dataObjectSet The {@link SS_List} to test.
@ -587,19 +587,19 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
* Examples
* --------
* Check that $members includes an entry with Email = sam@example.com:
* $this->assertDOSContains(array('Email' => '...@example.com'), $members);
*
* Check that $members includes entries with Email = sam@example.com and with
* $this->assertDOSContains(array('Email' => '...@example.com'), $members);
*
* Check that $members includes entries with Email = sam@example.com and with
* Email = ingo@example.com:
* $this->assertDOSContains(array(
* array('Email' => '...@example.com'),
* array('Email' => 'i...@example.com'),
* ), $members);
* $this->assertDOSContains(array(
* array('Email' => '...@example.com'),
* array('Email' => 'i...@example.com'),
* ), $members);
*/
public function assertDOSContains($matches, $dataObjectSet) {
$extracted = array();
foreach($dataObjectSet as $item) $extracted[] = $item->toMap();
foreach($matches as $match) {
$matched = false;
foreach($extracted as $i => $item) {
@ -615,35 +615,35 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
$this->assertTrue(
$matched,
"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)
);
}
}
}
/**
* 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.
*
*
* @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.
* @param $dataObjectSet The {@link SS_List} to test.
*
* 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:
* $this->assertDOSEquals(array(
* array('FirstName' =>'Sam', 'Surname' => 'Minnee'),
* array('FirstName' => 'Ingo', 'Surname' => 'Schommer'),
* ), $members);
* $this->assertDOSEquals(array(
* array('FirstName' =>'Sam', 'Surname' => 'Minnee'),
* array('FirstName' => 'Ingo', 'Surname' => 'Schommer'),
* ), $members);
*/
public function assertDOSEquals($matches, $dataObjectSet) {
if(!$dataObjectSet) return false;
$extracted = array();
foreach($dataObjectSet as $item) $extracted[] = $item->toMap();
foreach($matches as $match) {
$matched = false;
foreach($extracted as $i => $item) {
@ -659,11 +659,11 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
$this->assertTrue(
$matched,
"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)
);
}
// If we have leftovers than the DOS has extra data that shouldn't be there
$this->assertTrue(
(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 "
. "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
* pairs.
*
*
* @param $match The pattern to match. The pattern is a map of key-value pairs.
* @param $dataObjectSet The {@link SS_List} to test.
*
* Example
* --------
* 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) {
$extracted = array();
@ -692,12 +692,12 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
foreach($extracted as $i => $item) {
$this->assertTrue(
$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)
);
}
}
}
/**
* Helper function for the DOS matchers
*/
@ -723,17 +723,17 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
public static function using_temp_db() {
$dbConn = DB::getConn();
$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)));
}
public static function kill_temp_db() {
// Delete our temporary database
if(self::using_temp_db()) {
$dbConn = DB::getConn();
$dbName = $dbConn->currentDatabase();
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
foreach(ClassInfo::subclassesFor('DataExtension') as $class) {
$toCall = array($class, 'on_db_reset');
@ -745,7 +745,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
}
}
}
/**
* Remove all content from the temporary database.
*/
@ -753,8 +753,8 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
if(self::using_temp_db()) {
$dbadmin = new DatabaseAdmin();
$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
$classes = array_merge(ClassInfo::subclassesFor('DataExtension'), ClassInfo::subclassesFor('DataObject'));
foreach($classes as $class) {
@ -763,7 +763,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
}
}
}
public static function create_temp_db() {
// Disable PHPUnit error handling
restore_error_handler();
@ -784,13 +784,13 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
$st = Injector::inst()->create('SapphireTest');
$st->resetDBSchema();
// Reinstate PHPUnit error handling
set_error_handler(array('PHPUnit_Util_ErrorHandler', 'handleError'));
return $dbname;
}
public static function delete_all_temp_dbs() {
$prefix = defined('SS_DATABASE_PREFIX') ? SS_DATABASE_PREFIX : 'ss_';
foreach(DB::getConn()->allDatabaseNames() as $dbName) {
@ -805,7 +805,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
}
}
}
/**
* Reset the testing database's schema.
* @param $includeExtraDataObjects If true, the extraDataObjects tables will also be included
@ -846,7 +846,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
singleton('DataObject')->flushCache();
}
}
/**
* Create a member and group with the given permission code, and log in with it.
* Returns the member ID.
@ -861,23 +861,23 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
$permission->Code = $permCode;
$permission->write();
$group->Permissions()->add($permission);
$member = DataObject::get_one('Member', sprintf('"Email" = \'%s\'', "$permCode@example.org"));
if(!$member) $member = Injector::inst()->create('Member');
$member->FirstName = $permCode;
$member->Surname = "User";
$member->Email = "$permCode@example.org";
$member->write();
$group->Members()->add($member);
$this->cache_generatedMembers[$permCode] = $member;
}
$this->cache_generatedMembers[$permCode]->logIn();
return $this->cache_generatedMembers[$permCode]->ID;
}
/**
* Cache for logInWithPermission()
*/

View File

@ -182,18 +182,10 @@ end of each test.
$page->publish('Stage', 'Live');
}
// reset configuration for the test.
Config::nest();
// set custom configuration for the test.
Config::inst()->update('Foo', 'bar', 'Hello!');
}
public function tearDown() {
// restores the config variables
Config::unnest();
parent::tearDown();
}
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
@ -266,4 +284,4 @@ some `thirdparty/` directories add the following to the `phpunit.xml` configurat
* [api:TestRunner]
* [api:SapphireTest]
* [api:FunctionalTest]
* [api:FunctionalTest]

View File

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

View File

@ -82,23 +82,23 @@ class ConfigTest_TestNest extends Object implements TestOnly {
}
class ConfigTest extends SapphireTest {
public function testNest() {
// Check basic config
$this->assertEquals(3, Config::inst()->get('ConfigTest_TestNest', 'foo'));
$this->assertEquals(5, Config::inst()->get('ConfigTest_TestNest', 'bar'));
// Test nest copies data
Config::nest();
$this->assertEquals(3, Config::inst()->get('ConfigTest_TestNest', 'foo'));
$this->assertEquals(5, Config::inst()->get('ConfigTest_TestNest', 'bar'));
// Test nested data can be updated
Config::inst()->update('ConfigTest_TestNest', 'foo', 4);
$this->assertEquals(4, Config::inst()->get('ConfigTest_TestNest', 'foo'));
$this->assertEquals(5, Config::inst()->get('ConfigTest_TestNest', 'bar'));
// Test unnest restores data
Config::unnest();
$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
$this->assertNotContains('test_2b',
Config::inst()->get('ConfigStaticTest_Third', 'first', Config::UNINHERITED));
$this->assertNotContains('test_2b',
Config::inst()->get('ConfigStaticTest_Fourth', 'first', Config::UNINHERITED));
$this->assertNull(Config::inst()->get('ConfigStaticTest_Fourth', 'first', Config::UNINHERITED));
// 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()
// call (which can be buggy due to caching)
// This also checks that set can be called after the first uninherited get()
// call (which can be buggy due to caching)
Config::inst()->update('ConfigStaticTest_Fourth', 'first', array('test_4b'));
$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);
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));
$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() {
foreach (array('dev', 'test', 'live') as $env) {
Config::inst()->nest();
Config::nest();
Config::inst()->update('Director', 'environment_type', $env);
$config = $this->getConfigFixtureValue('Environment');
@ -403,13 +403,11 @@ class ConfigManifestTest extends SapphireTest {
);
}
Config::inst()->unnest();
Config::unnest();
}
}
public function testDynamicEnvironmentRules() {
Config::inst()->nest();
// First, make sure environment_type is live
Config::inst()->update('Director', 'environment_type', 'live');
$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
$this->assertEquals('dev', Config::inst()->get('ConfigManifestTest', 'DynamicEnvironment'));
Config::inst()->unnest();
}
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).
*
*
* @package framework
* @package tests
*/
class DevAdminControllerTest extends FunctionalTest {
public function setUp(){
parent::setUp();
Config::nest()->update('DevelopmentAdmin', 'registered_controllers', array(
Config::inst()->update('DevelopmentAdmin', 'registered_controllers', array(
'x1' => array(
'controller' => 'DevAdminControllerTest_Controller1',
'links' => array(
@ -27,45 +27,40 @@ class DevAdminControllerTest extends FunctionalTest {
)
));
}
public function tearDown(){
parent::tearDown();
Config::unnest();
}
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)
$this->assertContains(DevAdminControllerTest_Controller1::OK_MSG, $this->getCapture('/dev/x1'));
$this->assertContains(DevAdminControllerTest_Controller1::OK_MSG, $this->getCapture('/dev/x1/y1'));
}
public function testGoodRegisteredControllerStatus(){
// Check response code is 200/OK
$this->assertEquals(false, $this->getAndCheckForError('/dev/x1'));
$this->assertEquals(false, $this->getAndCheckForError('/dev/x1/y1'));
// Check response code is 500/ some sort of error
$this->assertEquals(true, $this->getAndCheckForError('/dev/x2'));
}
protected function getCapture($url){
$this->logInWithPermission('ADMIN');
ob_start();
$this->get($url);
$r = ob_get_contents();
ob_end_clean();
return $r;
}
protected function getAndCheckForError($url){
$this->logInWithPermission('ADMIN');
if(Director::is_cli()){
// when in CLI the admin controller throws exceptions
ob_start();
@ -75,10 +70,10 @@ class DevAdminControllerTest extends FunctionalTest {
ob_end_clean();
return true;
}
ob_end_clean();
return false;
}else{
// when in http the admin controller sets a response header
ob_start();
@ -87,30 +82,30 @@ class DevAdminControllerTest extends FunctionalTest {
return $resp->isError();
}
}
}
class DevAdminControllerTest_Controller1 extends Controller {
const OK_MSG = 'DevAdminControllerTest_Controller1 TEST OK';
private static $url_handlers = array(
'' => 'index',
'y1' => 'y1Action'
);
private static $allowed_actions = array(
'index',
'y1Action',
);
public function index(){
echo self::OK_MSG;
}
public function y1Action(){
echo self::OK_MSG;
}
}
}
}

View File

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

View File

@ -8,8 +8,9 @@ class MySQLDatabaseTest extends SapphireTest {
protected $extraDataObjects = array(
'MySQLDatabaseTest_DO',
);
public function setUp() {
parent::setUp();
if(DB::getConn() instanceof MySQLDatabase) {
MySQLDatabaseTest_DO::config()->db = array(
'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');
parent::setUp();
}
/**
* Check that once a schema has been generated, then it doesn't need any more updating
*/

View File

@ -1,16 +1,6 @@
<?php
class OembedTest extends SapphireTest {
public function setUp() {
parent::setUp();
Config::nest();
}
public function tearDown() {
Config::unnest();
parent::tearDown();
}
public function testGetOembedFromUrl() {
Config::inst()->update('Oembed', 'providers', array(
'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'));
$this->assertTrue($result!=false);
$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');
// Test magic.

View File

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