mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
API CHANGE Added FunctionalTest::
API CHANGE Added ->session() API CHANGE Added FunctionalTest:: API CHANGE Improved FunctionalTest's match by selector commands to produce less brittle output (rationalises whitespace) git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@55134 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
5562885c69
commit
5dff780a5d
@ -581,6 +581,11 @@ class ManifestBuilder {
|
|||||||
die("Cannot write manifest file! Check permissions of " . MANIFEST_FILE);
|
die("Cannot write manifest file! Check permissions of " . MANIFEST_FILE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static function includeEverything() {
|
||||||
|
global $_CLASS_MANIFEST;
|
||||||
|
foreach($_CLASS_MANIFEST as $classFile) require_once($classFile);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ class ContentController extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Draft/Archive security check - only CMS users should be able to look at stage/archived content
|
// Draft/Archive security check - only CMS users should be able to look at stage/archived content
|
||||||
if($this->URLSegment != 'Security' && (Versioned::current_archived_date() || (Versioned::current_stage() && Versioned::current_stage() != 'Live'))) {
|
if($this->URLSegment != 'Security' && !Session::get('unsecuredDraftSite') && (Versioned::current_archived_date() || (Versioned::current_stage() && Versioned::current_stage() != 'Live'))) {
|
||||||
if(!Permission::check('CMS_ACCESS_CMSMain')) {
|
if(!Permission::check('CMS_ACCESS_CMSMain')) {
|
||||||
$link = $this->Link();
|
$link = $this->Link();
|
||||||
$message = _t("ContentController.DRAFT_SITE_ACCESS_RESTRICTION", "You must log in with your CMS password in order to view the draft or archived content. <a href=\"%s\">Click here to go back to the published site.</a>");
|
$message = _t("ContentController.DRAFT_SITE_ACCESS_RESTRICTION", "You must log in with your CMS password in order to view the draft or archived content. <a href=\"%s\">Click here to go back to the published site.</a>");
|
||||||
|
@ -413,12 +413,15 @@ class Director {
|
|||||||
static function makeRelative($url) {
|
static function makeRelative($url) {
|
||||||
$base1 = self::absoluteBaseURL();
|
$base1 = self::absoluteBaseURL();
|
||||||
$base2 = self::baseFolder();
|
$base2 = self::baseFolder();
|
||||||
|
$base3 = self::baseURL();
|
||||||
|
|
||||||
// Allow for the accidental inclusion of a // in the URL
|
// Allow for the accidental inclusion of a // in the URL
|
||||||
$url = ereg_replace('([^:])//','\\1/',$url);
|
$url = ereg_replace('([^:])//','\\1/',$url);
|
||||||
|
|
||||||
if(substr($url,0,strlen($base1)) == $base1) return substr($url,strlen($base1));
|
if(substr($url,0,strlen($base1)) == $base1) return substr($url,strlen($base1));
|
||||||
if(substr($url,0,strlen($base2)) == $base2) return substr($url,strlen($base2));
|
else if(substr($url,0,strlen($base2)) == $base2) return substr($url,strlen($base2));
|
||||||
|
else if(substr($url,0,strlen($base3)) == $base3) return substr($url,strlen($base3));
|
||||||
|
|
||||||
return $url;
|
return $url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@ class PDODatabase extends Database {
|
|||||||
* @return boolean Returns true if successful
|
* @return boolean Returns true if successful
|
||||||
* @todo This shouldn't take any arguments; it should take the information given in the constructor instead.
|
* @todo This shouldn't take any arguments; it should take the information given in the constructor instead.
|
||||||
*/
|
*/
|
||||||
public function createDatabase($connect, $username, $password, $database) {
|
public function createDatabase() {
|
||||||
try {
|
try {
|
||||||
$dbh = new PDO($connect, $username, $password);
|
$dbh = new PDO($connect, $username, $password);
|
||||||
$stmt = $dbh->prepare("CREATE DATABASE $database");
|
$stmt = $dbh->prepare("CREATE DATABASE $database");
|
||||||
|
@ -20,21 +20,58 @@
|
|||||||
* </code>
|
* </code>
|
||||||
*/
|
*/
|
||||||
class FunctionalTest extends SapphireTest {
|
class FunctionalTest extends SapphireTest {
|
||||||
|
/**
|
||||||
|
* Set this to true on your sub-class to disable the use of themes in this test.
|
||||||
|
* This can be handy for functional testing of modules without having to worry about whether a user has changed
|
||||||
|
* behaviour by replacing the theme.
|
||||||
|
*/
|
||||||
|
static $disable_themes = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set this to true on your sub-class to use the draft site by default for every test in this class.
|
||||||
|
*/
|
||||||
|
static $use_draft_site = false;
|
||||||
|
|
||||||
protected $mainSession = null;
|
protected $mainSession = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CSSContentParser for the most recently requested page.
|
* CSSContentParser for the most recently requested page.
|
||||||
*/
|
*/
|
||||||
protected $cssParser = null;
|
protected $cssParser = null;
|
||||||
|
|
||||||
|
private $originalTheme = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link Session} object for this test
|
||||||
|
*/
|
||||||
|
function session() {
|
||||||
|
return $this->mainSession->session();
|
||||||
|
}
|
||||||
|
|
||||||
function setUp() {
|
function setUp() {
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$this->mainSession = new TestSession();
|
$this->mainSession = new TestSession();
|
||||||
|
|
||||||
|
// Disable theme, if necessary
|
||||||
|
if($this->stat('disable_themes')) {
|
||||||
|
$this->originalTheme = SSViewer::current_theme();
|
||||||
|
SSViewer::set_theme(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Switch to draft site, if necessary
|
||||||
|
if($this->stat('use_draft_site')) {
|
||||||
|
$this->useDraftSite();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function tearDown() {
|
function tearDown() {
|
||||||
parent::tearDown();
|
parent::tearDown();
|
||||||
$this->mainSession = null;
|
$this->mainSession = null;
|
||||||
|
|
||||||
|
// Re-enable theme, if previously disabled
|
||||||
|
if($this->stat('disable_themes')) {
|
||||||
|
SSViewer::set_theme($this->originalTheme);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -42,7 +79,9 @@ class FunctionalTest extends SapphireTest {
|
|||||||
*/
|
*/
|
||||||
function get($url) {
|
function get($url) {
|
||||||
$this->cssParser = null;
|
$this->cssParser = null;
|
||||||
return $this->mainSession->get($url);
|
$response = $this->mainSession->get($url);
|
||||||
|
if(is_object($response) && $response->getHeader('Location')) $response = $this->mainSession->followRedirection();
|
||||||
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,7 +89,9 @@ class FunctionalTest extends SapphireTest {
|
|||||||
*/
|
*/
|
||||||
function post($url, $data) {
|
function post($url, $data) {
|
||||||
$this->cssParser = null;
|
$this->cssParser = null;
|
||||||
return $this->mainSession->post($url, $data);
|
$response = $this->mainSession->post($url, $data);
|
||||||
|
if(is_object($response) && $response->getHeader('Location')) $response = $this->mainSession->followRedirection();
|
||||||
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,7 +100,9 @@ class FunctionalTest extends SapphireTest {
|
|||||||
*/
|
*/
|
||||||
function submitForm($formID, $button = null, $data = array()) {
|
function submitForm($formID, $button = null, $data = array()) {
|
||||||
$this->cssParser = null;
|
$this->cssParser = null;
|
||||||
return $this->mainSession->submitForm($formID, $button, $data);
|
$response = $this->mainSession->submitForm($formID, $button, $data);
|
||||||
|
if(is_object($response) && $response->getHeader('Location')) $response = $this->mainSession->followRedirection();
|
||||||
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,7 +132,7 @@ class FunctionalTest extends SapphireTest {
|
|||||||
*/
|
*/
|
||||||
function assertPartialMatchBySelector($selector, $expectedMatches) {
|
function assertPartialMatchBySelector($selector, $expectedMatches) {
|
||||||
$items = $this->cssParser()->getBySelector($selector);
|
$items = $this->cssParser()->getBySelector($selector);
|
||||||
foreach($items as $item) $actuals[$item . ''] = true;
|
foreach($items as $item) $actuals[] = trim(preg_replace("/[ \n\r\t]+/", " ", $item. ''));
|
||||||
|
|
||||||
foreach($expectedMatches as $match) {
|
foreach($expectedMatches as $match) {
|
||||||
if(!isset($actuals[$match])) {
|
if(!isset($actuals[$match])) {
|
||||||
@ -115,7 +158,7 @@ class FunctionalTest extends SapphireTest {
|
|||||||
*/
|
*/
|
||||||
function assertExactMatchBySelector($selector, $expectedMatches) {
|
function assertExactMatchBySelector($selector, $expectedMatches) {
|
||||||
$items = $this->cssParser()->getBySelector($selector);
|
$items = $this->cssParser()->getBySelector($selector);
|
||||||
foreach($items as $item) $actuals[] = $item . '';
|
foreach($items as $item) $actuals[] = trim(preg_replace("/[ \n\r\t]+/", " ", $item. ''));
|
||||||
|
|
||||||
if($expectedMatches != $actuals) {
|
if($expectedMatches != $actuals) {
|
||||||
throw new PHPUnit_Framework_AssertionFailedError(
|
throw new PHPUnit_Framework_AssertionFailedError(
|
||||||
@ -172,4 +215,22 @@ class FunctionalTest extends SapphireTest {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use the draft (stage) site for testing.
|
||||||
|
* This is helpful if you're not testing publication functionality and don't want "stage management" cluttering your test.
|
||||||
|
*/
|
||||||
|
function useDraftSite() {
|
||||||
|
$this->session()->inst_set('currentStage', 'Stage');
|
||||||
|
$this->session()->inst_set('unsecuredDraftSite', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a static variable from this class.
|
||||||
|
* Gets around PHP's lack of late static binding.
|
||||||
|
*/
|
||||||
|
function stat($varName) {
|
||||||
|
$className = get_class($this);
|
||||||
|
return eval("return {$className}::\$$varName;");
|
||||||
|
}
|
||||||
}
|
}
|
@ -60,6 +60,19 @@ class TestRunner extends Controller {
|
|||||||
echo "Please install PHPUnit using pear";
|
echo "Please install PHPUnit using pear";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function coverage() {
|
||||||
|
if(hasPhpUnit()) {
|
||||||
|
ManifestBuilder::includeEverything();
|
||||||
|
$tests = ClassInfo::subclassesFor('SapphireTest');
|
||||||
|
array_shift($tests);
|
||||||
|
unset($tests['FunctionalTest']);
|
||||||
|
|
||||||
|
$this->runTests($tests, true);
|
||||||
|
} else {
|
||||||
|
echo "Please install PHPUnit using pear";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run only a single test class
|
* Run only a single test class
|
||||||
@ -75,7 +88,7 @@ class TestRunner extends Controller {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function runTests($classList) {
|
function runTests($classList, $coverage = false) {
|
||||||
if(!Director::is_cli()) {
|
if(!Director::is_cli()) {
|
||||||
self::$default_reporter->writeHeader();
|
self::$default_reporter->writeHeader();
|
||||||
echo '<div class="info">';
|
echo '<div class="info">';
|
||||||
@ -100,7 +113,16 @@ class TestRunner extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*, array("reportDirectory" => "/Users/sminnee/phpunit-report")*/
|
/*, array("reportDirectory" => "/Users/sminnee/phpunit-report")*/
|
||||||
$testResult = PHPUnit_TextUI_TestRunner::run($suite);
|
if($coverage) {
|
||||||
|
$testResult = PHPUnit_TextUI_TestRunner::run($suite, array("reportDirectory" => "../assets/coverage-report"));
|
||||||
|
} else {
|
||||||
|
$testResult = PHPUnit_TextUI_TestRunner::run($suite);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($coverage) {
|
||||||
|
$coverageURL = Director::absoluteURL('assets/coverage-report');
|
||||||
|
echo "<p><a href=\"$coverageURL\">Coverage report available here</a></p>";
|
||||||
|
}
|
||||||
|
|
||||||
if(!Director::is_cli()) echo '</div>';
|
if(!Director::is_cli()) echo '</div>';
|
||||||
|
|
||||||
|
@ -80,7 +80,8 @@ class TestSession {
|
|||||||
* Get the most recent response's content
|
* Get the most recent response's content
|
||||||
*/
|
*/
|
||||||
function lastContent() {
|
function lastContent() {
|
||||||
return $this->lastResponse->getBody();
|
if(is_string($this->lastResponse)) return $this->lastResponse;
|
||||||
|
else return $this->lastResponse->getBody();
|
||||||
}
|
}
|
||||||
|
|
||||||
function cssParser() {
|
function cssParser() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user