mirror of
https://github.com/silverstripe/silverstripe-testsession
synced 2024-10-22 14:06:00 +02:00
Refactor to separate 'applyState' and 'saveState' functions
`appyState` will now only read the test session data and update the environment to relect that state. This is intended for things like database connections and mailer classes. Actions that need to alter state to apply it (eg creating a temp db) should be done in other actions such as 'start' `saveState` will only take an existing state object and persist it to a file Also addresses: [Connect to test database on session load](https://github.com/silverstripe/silverstripe-testsession/pull/63) [Skip Temp DB creation if state has no database prop](https://github.com/silverstripe/silverstripe-testsession/pull/64) Prevent re-creating session file on end (original issue for this PR)
This commit is contained in:
parent
4f68d5bae2
commit
1d8f112dd8
@ -311,7 +311,7 @@ class TestSessionController extends Controller
|
|||||||
|
|
||||||
$this->extend('onBeforeClear');
|
$this->extend('onBeforeClear');
|
||||||
|
|
||||||
$tempDB = new TempDatabase();
|
$tempDB = TempDatabase::create();
|
||||||
if ($tempDB->isUsed()) {
|
if ($tempDB->isUsed()) {
|
||||||
$tempDB->clearAllData();
|
$tempDB->clearAllData();
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,12 @@ use Exception;
|
|||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use LogicException;
|
use LogicException;
|
||||||
use SilverStripe\Assets\Filesystem;
|
use SilverStripe\Assets\Filesystem;
|
||||||
use SilverStripe\Core\Environment;
|
|
||||||
use SilverStripe\Control\Director;
|
use SilverStripe\Control\Director;
|
||||||
|
use SilverStripe\Control\Email\Email;
|
||||||
|
use SilverStripe\Control\Email\Mailer;
|
||||||
use SilverStripe\Control\HTTPRequest;
|
use SilverStripe\Control\HTTPRequest;
|
||||||
use SilverStripe\Core\Config\Configurable;
|
use SilverStripe\Core\Config\Configurable;
|
||||||
|
use SilverStripe\Core\Environment;
|
||||||
use SilverStripe\Core\Extensible;
|
use SilverStripe\Core\Extensible;
|
||||||
use SilverStripe\Core\Injector\Injectable;
|
use SilverStripe\Core\Injector\Injectable;
|
||||||
use SilverStripe\Core\Injector\Injector;
|
use SilverStripe\Core\Injector\Injector;
|
||||||
@ -20,6 +22,7 @@ use SilverStripe\ORM\Connect\TempDatabase;
|
|||||||
use SilverStripe\ORM\DatabaseAdmin;
|
use SilverStripe\ORM\DatabaseAdmin;
|
||||||
use SilverStripe\ORM\DB;
|
use SilverStripe\ORM\DB;
|
||||||
use SilverStripe\ORM\FieldType\DBDatetime;
|
use SilverStripe\ORM\FieldType\DBDatetime;
|
||||||
|
use SilverStripe\TestSession\TestSessionState;
|
||||||
use SilverStripe\Versioned\Versioned;
|
use SilverStripe\Versioned\Versioned;
|
||||||
use stdClass;
|
use stdClass;
|
||||||
|
|
||||||
@ -162,7 +165,9 @@ class TestSessionEnvironment
|
|||||||
$json = json_encode($state, JSON_FORCE_OBJECT);
|
$json = json_encode($state, JSON_FORCE_OBJECT);
|
||||||
$state = json_decode($json);
|
$state = json_decode($json);
|
||||||
|
|
||||||
$this->applyState($state);
|
$state = $this->createDatabase($state);
|
||||||
|
$state = $this->applyState($state);
|
||||||
|
$this->saveState($state);
|
||||||
|
|
||||||
// Back up /assets folder
|
// Back up /assets folder
|
||||||
$this->backupAssets();
|
$this->backupAssets();
|
||||||
@ -179,6 +184,7 @@ class TestSessionEnvironment
|
|||||||
$state = json_decode($json);
|
$state = json_decode($json);
|
||||||
|
|
||||||
$this->applyState($state);
|
$this->applyState($state);
|
||||||
|
$this->saveState($state);
|
||||||
|
|
||||||
$this->extend('onAfterUpdateTestSession');
|
$this->extend('onAfterUpdateTestSession');
|
||||||
}
|
}
|
||||||
@ -251,17 +257,65 @@ class TestSessionEnvironment
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Creates a TempDB
|
||||||
|
* Will modify state if the created database has a different name from what was in state
|
||||||
|
*
|
||||||
|
* @param stdClass $state
|
||||||
|
* @return stdClass $state
|
||||||
|
*/
|
||||||
|
public function createDatabase($state)
|
||||||
|
{
|
||||||
|
$dbCreate = isset($state->createDatabase) ? (bool) $state->createDatabase : false;
|
||||||
|
$dbName = (isset($state->database)) ? $state->database : null;
|
||||||
|
|
||||||
|
if ($dbName) {
|
||||||
|
$dbExists = DB::get_conn()->databaseExists($dbName);
|
||||||
|
} else {
|
||||||
|
$dbExists = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$databaseConfig = DB::getConfig();
|
||||||
|
if (!$dbExists && $dbCreate) {
|
||||||
|
$this->oldDatabaseName = $databaseConfig['database'];
|
||||||
|
// Create a new one with a randomized name
|
||||||
|
$tempDB = TempDatabase::create();
|
||||||
|
$dbName = $tempDB->build();
|
||||||
|
|
||||||
|
$state->database = $dbName; // In case it's changed by the call to SapphireTest::create_temp_db();
|
||||||
|
|
||||||
|
// Set existing one, assumes it already has been created
|
||||||
|
$prefix = Environment::getEnv('SS_DATABASE_PREFIX') ?: 'ss_';
|
||||||
|
$pattern = strtolower(sprintf('#^%stmpdb.*#', preg_quote($prefix, '#')));
|
||||||
|
if (!preg_match($pattern, $dbName)) {
|
||||||
|
throw new InvalidArgumentException("Invalid database name format");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($dbExists || $dbCreate) {
|
||||||
|
// Connect to the new database, overwriting the old DB connection (if any)
|
||||||
|
$databaseConfig['database'] = $dbName; // Instead of calling DB::set_alternative_db_name();
|
||||||
|
DB::connect($databaseConfig);
|
||||||
|
TestSessionState::create()->write(); // initialize the session state
|
||||||
|
}
|
||||||
|
|
||||||
|
return $state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes a state object and applies environment transformations to current application environment
|
||||||
|
*
|
||||||
|
* Does not persist any changes to the the state object - @see saveState for persistence
|
||||||
|
*
|
||||||
* Assumes the database has already been created in startTestSession(), as this method can be called from
|
* Assumes the database has already been created in startTestSession(), as this method can be called from
|
||||||
* _config.php where we don't yet have a DB connection.
|
* _config.php where we don't yet have a DB connection.
|
||||||
*
|
*
|
||||||
* Persists the state to the filesystem.
|
|
||||||
*
|
|
||||||
* You can extend this by creating an Extension object and implementing either onBeforeApplyState() or
|
* You can extend this by creating an Extension object and implementing either onBeforeApplyState() or
|
||||||
* onAfterApplyState() to add your own test state handling in.
|
* onAfterApplyState() to add your own test state handling in.
|
||||||
*
|
*
|
||||||
* @param mixed $state
|
* @param mixed $state
|
||||||
* @throws LogicException
|
* @throws LogicException
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
|
* @return mixed $state
|
||||||
*/
|
*/
|
||||||
public function applyState($state)
|
public function applyState($state)
|
||||||
{
|
{
|
||||||
@ -271,64 +325,21 @@ class TestSessionEnvironment
|
|||||||
$databaseConfig = DB::getConfig();
|
$databaseConfig = DB::getConfig();
|
||||||
$this->oldDatabaseName = $databaseConfig['database'];
|
$this->oldDatabaseName = $databaseConfig['database'];
|
||||||
|
|
||||||
// Load existing state from $this->state into $state, if there is any
|
|
||||||
$oldState = $this->getState();
|
|
||||||
|
|
||||||
if ($oldState) {
|
|
||||||
foreach ($oldState as $k => $v) {
|
|
||||||
if (!isset($state->$k)) {
|
|
||||||
$state->$k = $v; // Don't overwrite stuff in $state, as that's the new state
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensure we have a connection to the database
|
// ensure we have a connection to the database
|
||||||
$this->connectToDatabase($state);
|
$this->connectToDatabase($state);
|
||||||
|
|
||||||
// Database
|
|
||||||
if (!$this->isRunningTests()) {
|
|
||||||
$dbName = (isset($state->database)) ? $state->database : null;
|
|
||||||
|
|
||||||
if ($dbName) {
|
|
||||||
$dbExists = DB::get_conn()->databaseExists($dbName);
|
|
||||||
} else {
|
|
||||||
$dbExists = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$dbExists) {
|
|
||||||
// Create a new one with a randomized name
|
|
||||||
$tempDB = new TempDatabase();
|
|
||||||
$dbName = $tempDB->build();
|
|
||||||
|
|
||||||
$state->database = $dbName; // In case it's changed by the call to SapphireTest::create_temp_db();
|
|
||||||
|
|
||||||
// Set existing one, assumes it already has been created
|
|
||||||
$prefix = Environment::getEnv('SS_DATABASE_PREFIX') ?: 'ss_';
|
|
||||||
$pattern = strtolower(sprintf('#^%stmpdb.*#', preg_quote($prefix, '#')));
|
|
||||||
if (!preg_match($pattern, $dbName)) {
|
|
||||||
throw new InvalidArgumentException("Invalid database name format");
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->oldDatabaseName = $databaseConfig['database'];
|
|
||||||
$databaseConfig['database'] = $dbName; // Instead of calling DB::set_alternative_db_name();
|
|
||||||
|
|
||||||
// Connect to the new database, overwriting the old DB connection (if any)
|
|
||||||
DB::connect($databaseConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
TestSessionState::create()->write(); // initialize the session state
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mailer
|
// Mailer
|
||||||
$mailer = (isset($state->mailer)) ? $state->mailer : null;
|
$mailer = (isset($state->mailer)) ? $state->mailer : null;
|
||||||
|
|
||||||
if ($mailer) {
|
if ($mailer) {
|
||||||
if (!class_exists($mailer) || !is_subclass_of($mailer, 'SilverStripe\\Control\\Email\\Mailer')) {
|
if (!class_exists($mailer) || !is_subclass_of($mailer, Mailer::class)) {
|
||||||
throw new InvalidArgumentException(sprintf(
|
throw new InvalidArgumentException(sprintf(
|
||||||
'Class "%s" is not a valid class, or subclass of Mailer',
|
'Class "%s" is not a valid class, or subclass of Mailer',
|
||||||
$mailer
|
$mailer
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
Injector::inst()->registerService(new $mailer(), Mailer::class);
|
||||||
|
Email::config()->set("send_all_emails_to", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Date and time
|
// Date and time
|
||||||
@ -342,11 +353,24 @@ class TestSessionEnvironment
|
|||||||
$state->datetime
|
$state->datetime
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
DBDatetime::set_mock_now($state->datetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->saveState($state);
|
// Allows inclusion of a PHP file, usually with procedural commands
|
||||||
|
// to set up required test state. The file can be generated
|
||||||
|
// through {@link TestSessionStubCodeWriter}, and the session state
|
||||||
|
// set through {@link TestSessionController->set()} and the
|
||||||
|
// 'testsession.stubfile' state parameter.
|
||||||
|
if (isset($state->stubfile)) {
|
||||||
|
$file = $state->stubfile;
|
||||||
|
if (!Director::isLive() && $file && file_exists($file)) {
|
||||||
|
include_once($file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$this->extend('onAfterApplyState');
|
$this->extend('onAfterApplyState', $state);
|
||||||
|
|
||||||
|
return $state;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -454,7 +478,7 @@ class TestSessionEnvironment
|
|||||||
$this->restoreAssets();
|
$this->restoreAssets();
|
||||||
|
|
||||||
// Reset DB
|
// Reset DB
|
||||||
$tempDB = new TempDatabase();
|
$tempDB = TempDatabase::create();
|
||||||
if ($tempDB->isUsed()) {
|
if ($tempDB->isUsed()) {
|
||||||
$state = $this->getState();
|
$state = $this->getState();
|
||||||
$dbConn = DB::get_schema();
|
$dbConn = DB::get_schema();
|
||||||
@ -476,6 +500,8 @@ class TestSessionEnvironment
|
|||||||
/**
|
/**
|
||||||
* Loads a YAML fixture into the database as part of the {@link TestSessionController}.
|
* Loads a YAML fixture into the database as part of the {@link TestSessionController}.
|
||||||
*
|
*
|
||||||
|
* Writes loaded fixture files to $state->fixtures
|
||||||
|
*
|
||||||
* @param string $fixtureFile The .yml file to load
|
* @param string $fixtureFile The .yml file to load
|
||||||
* @return FixtureFactory The loaded fixture
|
* @return FixtureFactory The loaded fixture
|
||||||
* @throws LogicException
|
* @throws LogicException
|
||||||
@ -500,7 +526,7 @@ class TestSessionEnvironment
|
|||||||
|
|
||||||
$state = $this->getState();
|
$state = $this->getState();
|
||||||
$state->fixtures[] = $fixtureFile;
|
$state->fixtures[] = $fixtureFile;
|
||||||
$this->applyState($state);
|
$this->saveState($state);
|
||||||
|
|
||||||
return $fixture;
|
return $fixture;
|
||||||
}
|
}
|
||||||
@ -544,10 +570,12 @@ class TestSessionEnvironment
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure that there is a connection to the database
|
* Ensure that there is a connection to the database
|
||||||
*
|
*
|
||||||
* @param mixed $state
|
* @param mixed $state
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function connectToDatabase($state = null) {
|
public function connectToDatabase($state = null)
|
||||||
|
{
|
||||||
if ($state == null) {
|
if ($state == null) {
|
||||||
$state = $this->getState();
|
$state = $this->getState();
|
||||||
}
|
}
|
||||||
|
@ -57,41 +57,26 @@ class TestSessionHTTPMiddleware implements HTTPMiddleware
|
|||||||
*/
|
*/
|
||||||
protected function loadTestState(HTTPRequest $request)
|
protected function loadTestState(HTTPRequest $request)
|
||||||
{
|
{
|
||||||
$testState = $this->testSessionEnvironment->getState();
|
$state = $this->testSessionEnvironment->getState();
|
||||||
|
$this->testSessionEnvironment->applyState($state);
|
||||||
// Date and time
|
|
||||||
if (isset($testState->datetime)) {
|
|
||||||
DBDatetime::set_mock_now($testState->datetime);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register mailer
|
|
||||||
if (isset($testState->mailer)) {
|
|
||||||
$mailer = $testState->mailer;
|
|
||||||
Injector::inst()->registerService(new $mailer(), Mailer::class);
|
|
||||||
Email::config()->set("send_all_emails_to", null);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connect to the test session database
|
|
||||||
$this->testSessionEnvironment->connectToDatabase();
|
|
||||||
|
|
||||||
// Allows inclusion of a PHP file, usually with procedural commands
|
|
||||||
// to set up required test state. The file can be generated
|
|
||||||
// through {@link TestSessionStubCodeWriter}, and the session state
|
|
||||||
// set through {@link TestSessionController->set()} and the
|
|
||||||
// 'testsession.stubfile' state parameter.
|
|
||||||
if (isset($testState->stubfile)) {
|
|
||||||
$file = $testState->stubfile;
|
|
||||||
if (!Director::isLive() && $file && file_exists($file)) {
|
|
||||||
include_once($file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param HTTPRequest $request
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
protected function restoreTestState(HTTPRequest $request)
|
protected function restoreTestState(HTTPRequest $request)
|
||||||
{
|
{
|
||||||
// Store PHP session
|
// Store PHP session
|
||||||
$state = $this->testSessionEnvironment->getState();
|
$state = $this->testSessionEnvironment->getState();
|
||||||
$state->session = $request->getSession()->getAll();
|
$state->session = $request->getSession()->getAll();
|
||||||
$this->testSessionEnvironment->applyState($state);
|
|
||||||
|
// skip saving file if the session is being closed (all test properties are removed except session)
|
||||||
|
$keys = get_object_vars($state);
|
||||||
|
if (count($keys) <= 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->testSessionEnvironment->saveState($state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
0
tests/stubs/_manifest_exclude
Normal file
0
tests/stubs/_manifest_exclude
Normal file
3
tests/stubs/teststub.php
Normal file
3
tests/stubs/teststub.php
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
define('TESTSESSION_STUBFILE', false);
|
278
tests/unit/TestSessionControllerTest.php
Normal file
278
tests/unit/TestSessionControllerTest.php
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\TestSession\Tests\Unit;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
|
use LogicException;
|
||||||
|
use SilverStripe\Control\Director;
|
||||||
|
use SilverStripe\Control\Email\Mailer;
|
||||||
|
use SilverStripe\Control\HTTPRequest;
|
||||||
|
use SilverStripe\Control\Session;
|
||||||
|
use SilverStripe\Core\Injector\Injector;
|
||||||
|
use SilverStripe\Core\Manifest\ModuleLoader;
|
||||||
|
use SilverStripe\Dev\SapphireTest;
|
||||||
|
use SilverStripe\ORM\FieldType\DBDatetime;
|
||||||
|
use SilverStripe\TestSession\TestSessionController;
|
||||||
|
use SilverStripe\TestSession\TestSessionEnvironment;
|
||||||
|
use SilverStripe\TestSession\TestSessionHTTPMiddleware;
|
||||||
|
use stdClass;
|
||||||
|
use SilverStripe\ORM\Connect\TempDatabase;
|
||||||
|
use SilverStripe\Core\Config\Config;
|
||||||
|
|
||||||
|
class TestSessionControllerTest extends SapphireTest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var TestSessionEnvironment|PHPUnit_Framework_MockObject_MockObject
|
||||||
|
*/
|
||||||
|
private $testSessionEnvironment;
|
||||||
|
|
||||||
|
protected $usesDatabase = true;
|
||||||
|
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
Injector::inst()->unregisterNamedObject(TestSessionEnvironment::class);
|
||||||
|
Injector::inst()->registerService(
|
||||||
|
$this->createMock(TestSessionEnvironment::class),
|
||||||
|
TestSessionEnvironment::class
|
||||||
|
);
|
||||||
|
$this->testSessionEnvironment = TestSessionEnvironment::singleton();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIndex()
|
||||||
|
{
|
||||||
|
$controller = new TestSessionController();
|
||||||
|
$this->assertContains('Start a new test session', (string) $controller->index());
|
||||||
|
|
||||||
|
$env = $this->testSessionEnvironment;
|
||||||
|
$env->method('isRunningTests')
|
||||||
|
->willReturn(true);
|
||||||
|
|
||||||
|
$state = new stdClass();
|
||||||
|
$state->showme = 'test';
|
||||||
|
$env->method('getState')
|
||||||
|
->willReturn($state);
|
||||||
|
|
||||||
|
$html = (string) $controller->index();
|
||||||
|
$this->assertContains('Test session in progress.', $html);
|
||||||
|
$this->assertContains('showme:', $html);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testStartNonGlobalImport()
|
||||||
|
{
|
||||||
|
DBDatetime::set_mock_now(1552525373);
|
||||||
|
$params = [
|
||||||
|
'datetime' => [
|
||||||
|
'date' => DBDatetime::now()->Date(),
|
||||||
|
],
|
||||||
|
'importDatabasePath' => '/somepath',
|
||||||
|
'importDatabaseFilename' => 'bigOldb.sql',
|
||||||
|
'requireDefaultRecords' => '1',
|
||||||
|
'fixture' => 'fixture.yml',
|
||||||
|
];
|
||||||
|
Director::mockRequest(function ($request) {
|
||||||
|
$controller = new TestSessionController();
|
||||||
|
$controller->setRequest($request);
|
||||||
|
|
||||||
|
$env = $this->testSessionEnvironment;
|
||||||
|
$state = new stdClass();
|
||||||
|
|
||||||
|
$env->method('getState')
|
||||||
|
->willReturn($state);
|
||||||
|
|
||||||
|
$env->expects($this->once())
|
||||||
|
->method('startTestSession')
|
||||||
|
->with(
|
||||||
|
[
|
||||||
|
'datetime' => 'Mar 14, 2019 00:00:00',
|
||||||
|
'importDatabasePath' => '/somepath',
|
||||||
|
'importDatabaseFilename' => 'bigOldb.sql',
|
||||||
|
'requireDefaultRecords' => '1',
|
||||||
|
'fixture' => 'fixture.yml',
|
||||||
|
],
|
||||||
|
$this->isType('string')
|
||||||
|
);
|
||||||
|
|
||||||
|
// cannot do an import and default records
|
||||||
|
$env->expects($this->never())
|
||||||
|
->method('requireDefaultRecords');
|
||||||
|
|
||||||
|
$env->expects($this->once())
|
||||||
|
->method('loadFixtureIntoDb')
|
||||||
|
->with('fixture.yml');
|
||||||
|
|
||||||
|
$html = (string) $controller->start();
|
||||||
|
$this->assertContains('Test session in progress.', $html);
|
||||||
|
|
||||||
|
$this->assertNotNull($request->getSession()->get('TestSessionId'));
|
||||||
|
}, 'dev/testsession/start', $params);
|
||||||
|
|
||||||
|
DBDatetime::clear_mock_now();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testStartNonGlobalDefaultRecords()
|
||||||
|
{
|
||||||
|
$params = [
|
||||||
|
'requireDefaultRecords' => '1',
|
||||||
|
];
|
||||||
|
Director::mockRequest(function ($request) {
|
||||||
|
$controller = new TestSessionController();
|
||||||
|
$controller->setRequest($request);
|
||||||
|
|
||||||
|
$env = $this->testSessionEnvironment;
|
||||||
|
$state = new stdClass();
|
||||||
|
|
||||||
|
$env->method('getState')
|
||||||
|
->willReturn($state);
|
||||||
|
|
||||||
|
$env->expects($this->once())
|
||||||
|
->method('startTestSession')
|
||||||
|
->with(
|
||||||
|
[
|
||||||
|
'requireDefaultRecords' => '1',
|
||||||
|
],
|
||||||
|
$this->isType('string')
|
||||||
|
);
|
||||||
|
|
||||||
|
$env->expects($this->once())
|
||||||
|
->method('requireDefaultRecords')
|
||||||
|
->with();
|
||||||
|
|
||||||
|
$controller->start();
|
||||||
|
}, 'dev/testsession/start', $params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetNotRunning()
|
||||||
|
{
|
||||||
|
$this->expectException(LogicException::class);
|
||||||
|
$params = [];
|
||||||
|
Director::mockRequest(function ($request) {
|
||||||
|
$controller = new TestSessionController();
|
||||||
|
$controller->setRequest($request);
|
||||||
|
|
||||||
|
$controller->set();
|
||||||
|
}, 'dev/testsession/set', $params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetRunning()
|
||||||
|
{
|
||||||
|
DBDatetime::set_mock_now(1552525373);
|
||||||
|
$params = [
|
||||||
|
'datetime' => [
|
||||||
|
'date' => DBDatetime::now()->Date(),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
Director::mockRequest(function ($request) {
|
||||||
|
$controller = new TestSessionController();
|
||||||
|
$controller->setRequest($request);
|
||||||
|
|
||||||
|
$env = $this->testSessionEnvironment;
|
||||||
|
$state = new stdClass();
|
||||||
|
|
||||||
|
$env->method('isRunningTests')
|
||||||
|
->willReturn(true);
|
||||||
|
|
||||||
|
$env->method('getState')
|
||||||
|
->willReturn($state);
|
||||||
|
|
||||||
|
$env->expects($this->once())
|
||||||
|
->method('updateTestSession')
|
||||||
|
->with(
|
||||||
|
[
|
||||||
|
'datetime' => 'Mar 14, 2019 00:00:00',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$html = (string) $controller->set();
|
||||||
|
$this->assertContains('Test session in progress.', $html);
|
||||||
|
}, 'dev/testsession/set', $params);
|
||||||
|
|
||||||
|
DBDatetime::clear_mock_now();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testClearNotRunning()
|
||||||
|
{
|
||||||
|
$this->expectException(LogicException::class);
|
||||||
|
$params = [];
|
||||||
|
Director::mockRequest(function ($request) {
|
||||||
|
$controller = new TestSessionController();
|
||||||
|
$controller->setRequest($request);
|
||||||
|
|
||||||
|
$controller->clear();
|
||||||
|
}, 'dev/testsession/clear', $params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testClearRunning()
|
||||||
|
{
|
||||||
|
|
||||||
|
$params = [];
|
||||||
|
Director::mockRequest(function ($request) {
|
||||||
|
$controller = new TestSessionController();
|
||||||
|
$controller->setRequest($request);
|
||||||
|
|
||||||
|
$env = $this->testSessionEnvironment;
|
||||||
|
$state = new stdClass();
|
||||||
|
|
||||||
|
$env->method('isRunningTests')
|
||||||
|
->willReturn(true);
|
||||||
|
|
||||||
|
$env->method('getState')
|
||||||
|
->willReturn($state);
|
||||||
|
|
||||||
|
Config::nest();
|
||||||
|
Config::modify()->set(TempDatabase::class, 'factory', new class {
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
$mockdb = $this->createMock(TempDatabase::class);
|
||||||
|
$mockdb->method('isUsed')->willReturn(true);
|
||||||
|
$mockdb->expects($this->once())
|
||||||
|
->method('clearAllData');
|
||||||
|
return $mockdb;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$msg = $controller->clear();
|
||||||
|
Config::unnest();
|
||||||
|
$this->assertEquals('Cleared database and test state', $msg);
|
||||||
|
}, 'dev/testsession/clear', $params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEndNotRunning()
|
||||||
|
{
|
||||||
|
$this->expectException(LogicException::class);
|
||||||
|
$params = [];
|
||||||
|
Director::mockRequest(function ($request) {
|
||||||
|
$controller = new TestSessionController();
|
||||||
|
$controller->setRequest($request);
|
||||||
|
|
||||||
|
$controller->end();
|
||||||
|
}, 'dev/testsession/end', $params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEndRunning()
|
||||||
|
{
|
||||||
|
$params = [];
|
||||||
|
Director::mockRequest(function ($request) {
|
||||||
|
$controller = new TestSessionController();
|
||||||
|
$controller->setRequest($request);
|
||||||
|
|
||||||
|
$env = $this->testSessionEnvironment;
|
||||||
|
$state = new stdClass();
|
||||||
|
|
||||||
|
$env->method('isRunningTests')
|
||||||
|
->willReturn(true);
|
||||||
|
|
||||||
|
$env->method('getState')
|
||||||
|
->willReturn($state);
|
||||||
|
|
||||||
|
$env->expects($this->once())
|
||||||
|
->method('endTestSession');
|
||||||
|
|
||||||
|
$html = (string) $controller->end();
|
||||||
|
$this->assertContains('Test session ended', $html);
|
||||||
|
|
||||||
|
$this->assertNull($request->getSession()->get('TestSessionId'));
|
||||||
|
}, 'dev/testsession/end', $params);
|
||||||
|
}
|
||||||
|
}
|
162
tests/unit/TestSessionEnvironmentTest.php
Normal file
162
tests/unit/TestSessionEnvironmentTest.php
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\TestSession\Tests\Unit;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
|
use SilverStripe\BehatExtension\Utility\TestMailer;
|
||||||
|
use SilverStripe\Control\Email\Mailer;
|
||||||
|
use SilverStripe\Core\Injector\Injector;
|
||||||
|
use SilverStripe\Core\Manifest\ModuleLoader;
|
||||||
|
use SilverStripe\Dev\SapphireTest;
|
||||||
|
use SilverStripe\ORM\Connect\TempDatabase;
|
||||||
|
use SilverStripe\ORM\DB;
|
||||||
|
use SilverStripe\ORM\FieldType\DBDatetime;
|
||||||
|
use SilverStripe\TestSession\TestSessionEnvironment;
|
||||||
|
use SilverStripe\TestSession\TestSessionState;
|
||||||
|
use stdClass;
|
||||||
|
|
||||||
|
class TestSessionEnvironmentTest extends SapphireTest
|
||||||
|
{
|
||||||
|
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
Injector::inst()->unregisterNamedObject(TestSessionEnvironment::class);
|
||||||
|
Injector::inst()->registerService(
|
||||||
|
new TestSessionEnvironment,
|
||||||
|
TestSessionEnvironment::class
|
||||||
|
);
|
||||||
|
$this->testSessionEnvironment = TestSessionEnvironment::singleton();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testApplyStateNoModification()
|
||||||
|
{
|
||||||
|
$state = new stdClass();
|
||||||
|
$state->testprop = '';
|
||||||
|
|
||||||
|
$env = new TestSessionEnvironment();
|
||||||
|
$afterApply = $env->applyState($state);
|
||||||
|
|
||||||
|
$this->assertSame($state, $afterApply);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testApplyStateDBConnect()
|
||||||
|
{
|
||||||
|
$state = new stdClass();
|
||||||
|
$state->testprop = '';
|
||||||
|
|
||||||
|
$env = $this->getMockBuilder(TestSessionEnvironment::class)
|
||||||
|
->setMethodsExcept(['applyState'])
|
||||||
|
->getMock();
|
||||||
|
|
||||||
|
$env->expects($this->once())
|
||||||
|
->method('connectToDatabase');
|
||||||
|
|
||||||
|
$env->applyState($state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testApplyStateDatetime()
|
||||||
|
{
|
||||||
|
$state = new stdClass();
|
||||||
|
$now = new DateTime();
|
||||||
|
$now->modify('-1 day');
|
||||||
|
$state->datetime = $now->format('Y-m-d H:i:s');
|
||||||
|
|
||||||
|
$env = new TestSessionEnvironment();
|
||||||
|
$env->applyState($state);
|
||||||
|
$date = new DateTime();
|
||||||
|
$this->assertNotEquals($date->getTimestamp(), DBDatetime::now()->getTimestamp());
|
||||||
|
$this->assertEquals($now->getTimestamp(), DBDatetime::now()->getTimestamp());
|
||||||
|
|
||||||
|
$state->datetime = 'invalid format';
|
||||||
|
$this->expectExceptionMessage('Invalid date format "invalid format", use yyyy-MM-dd HH:mm:ss');
|
||||||
|
$env->applyState($state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAppyStateMailer()
|
||||||
|
{
|
||||||
|
|
||||||
|
$state = new stdClass();
|
||||||
|
$state->mailer = TestMailer::class;
|
||||||
|
$env = new TestSessionEnvironment();
|
||||||
|
|
||||||
|
$env->applyState($state);
|
||||||
|
|
||||||
|
$mailer = Injector::inst()->get(Mailer::class);
|
||||||
|
$this->assertEquals(TestMailer::class, get_class($mailer));
|
||||||
|
|
||||||
|
$state->mailer = 'stdClass';
|
||||||
|
$this->expectExceptionMessage('Class "stdClass" is not a valid class, or subclass of Mailer');
|
||||||
|
$env->applyState($state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAppyStateStub()
|
||||||
|
{
|
||||||
|
|
||||||
|
$module = ModuleLoader::getModule('silverstripe/testsession');
|
||||||
|
$state = new stdClass();
|
||||||
|
|
||||||
|
$state->stubfile = $module->getPath() . DIRECTORY_SEPARATOR . 'tests/stubs/teststub.php';
|
||||||
|
|
||||||
|
$env = new TestSessionEnvironment();
|
||||||
|
|
||||||
|
$this->assertFalse(defined('TESTSESSION_STUBFILE'));
|
||||||
|
|
||||||
|
$env->applyState($state);
|
||||||
|
|
||||||
|
$this->assertTrue(defined('TESTSESSION_STUBFILE'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testConnectToDatabase()
|
||||||
|
{
|
||||||
|
$env = new TestSessionEnvironment();
|
||||||
|
$dbExisting = DB::get_conn()->getSelectedDatabase();
|
||||||
|
|
||||||
|
$env->connectToDatabase(new stdClass);
|
||||||
|
$db = DB::get_conn()->getSelectedDatabase();
|
||||||
|
$this->assertEquals($dbExisting, $db);
|
||||||
|
|
||||||
|
$tempDB = new TempDatabase();
|
||||||
|
$dbName = $tempDB->build();
|
||||||
|
|
||||||
|
$state = new stdClass();
|
||||||
|
$state->database = $dbName;
|
||||||
|
$env->connectToDatabase($state);
|
||||||
|
$db = DB::get_conn()->getSelectedDatabase();
|
||||||
|
$this->assertEquals($dbName, $db);
|
||||||
|
|
||||||
|
$tempDB->kill();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreateDatabase()
|
||||||
|
{
|
||||||
|
$env = new TestSessionEnvironment();
|
||||||
|
$dbExisting = DB::get_conn()->getSelectedDatabase();
|
||||||
|
|
||||||
|
$state = new stdClass;
|
||||||
|
|
||||||
|
$env->createDatabase($state);
|
||||||
|
$db = DB::get_conn()->getSelectedDatabase();
|
||||||
|
$this->assertEquals($dbExisting, $db);
|
||||||
|
|
||||||
|
|
||||||
|
$state = new stdClass();
|
||||||
|
$state->createDatabase = true;
|
||||||
|
$env->createDatabase($state);
|
||||||
|
$db = DB::get_conn()->getSelectedDatabase();
|
||||||
|
$this->assertNotEquals($dbExisting, $db);
|
||||||
|
|
||||||
|
// check the TestSessionState object has been created
|
||||||
|
$stateObj = TestSessionState::get()->first();
|
||||||
|
$this->assertNotNull($stateObj);
|
||||||
|
$this->assertTrue($stateObj->exists());
|
||||||
|
|
||||||
|
$tempDB = new TempDatabase('default');
|
||||||
|
$tempDB->kill();
|
||||||
|
|
||||||
|
$state = new stdClass();
|
||||||
|
$state->database = $dbExisting;
|
||||||
|
|
||||||
|
$env->connectToDatabase($state);
|
||||||
|
}
|
||||||
|
}
|
103
tests/unit/TestSessionHTTPMiddlewareTest.php
Normal file
103
tests/unit/TestSessionHTTPMiddlewareTest.php
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\TestSession\Tests\Unit;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
|
use SilverStripe\Control\HTTPRequest;
|
||||||
|
use SilverStripe\Control\Session;
|
||||||
|
use SilverStripe\Core\Injector\Injector;
|
||||||
|
use SilverStripe\Dev\SapphireTest;
|
||||||
|
use SilverStripe\ORM\FieldType\DBDatetime;
|
||||||
|
use SilverStripe\TestSession\TestSessionEnvironment;
|
||||||
|
use SilverStripe\TestSession\TestSessionHTTPMiddleware;
|
||||||
|
use stdClass;
|
||||||
|
use SilverStripe\Control\Email\Mailer;
|
||||||
|
use SilverStripe\Core\Manifest\ModuleLoader;
|
||||||
|
|
||||||
|
class TestSessionHTTPMiddlewareTest extends SapphireTest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var TestSessionEnvironment
|
||||||
|
*/
|
||||||
|
private $testSessionEnvironment;
|
||||||
|
|
||||||
|
protected $usesDatabase = true;
|
||||||
|
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
Injector::inst()->registerService(
|
||||||
|
$this->createMock(TestSessionEnvironment::class),
|
||||||
|
TestSessionEnvironment::class
|
||||||
|
);
|
||||||
|
$this->testSessionEnvironment = TestSessionEnvironment::singleton();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testProcessNoTestRunning()
|
||||||
|
{
|
||||||
|
$env = $this->testSessionEnvironment;
|
||||||
|
|
||||||
|
// setup expected calls on environment
|
||||||
|
$env->expects($this->never())
|
||||||
|
->method('getState');
|
||||||
|
|
||||||
|
$env->expects($this->never())
|
||||||
|
->method('applyState');
|
||||||
|
|
||||||
|
Injector::nest();
|
||||||
|
|
||||||
|
Injector::inst()->registerService(
|
||||||
|
$env,
|
||||||
|
TestSessionEnvironment::class
|
||||||
|
);
|
||||||
|
|
||||||
|
$middleware = new TestSessionHTTPMiddleware();
|
||||||
|
// Mock request
|
||||||
|
$session = new Session([]);
|
||||||
|
$request = new HTTPRequest('GET', '/');
|
||||||
|
$request->setSession($session);
|
||||||
|
$delegate = function () {
|
||||||
|
// noop
|
||||||
|
};
|
||||||
|
$middleware->process($request, $delegate);
|
||||||
|
|
||||||
|
Injector::unnest();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testProcessTestsRunning()
|
||||||
|
{
|
||||||
|
|
||||||
|
$state = new stdClass();
|
||||||
|
$env = $this->testSessionEnvironment;
|
||||||
|
|
||||||
|
$env->method('isRunningTests')
|
||||||
|
->willReturn(true);
|
||||||
|
|
||||||
|
// setup expected calls on environment
|
||||||
|
$env->expects($this->exactly(2))
|
||||||
|
->method('getState')
|
||||||
|
->willReturn($state);
|
||||||
|
|
||||||
|
$env->expects($this->once())
|
||||||
|
->method('applyState');
|
||||||
|
|
||||||
|
Injector::nest();
|
||||||
|
|
||||||
|
Injector::inst()->registerService(
|
||||||
|
$env,
|
||||||
|
TestSessionEnvironment::class
|
||||||
|
);
|
||||||
|
|
||||||
|
$middleware = new TestSessionHTTPMiddleware();
|
||||||
|
// Mock request
|
||||||
|
$session = new Session([]);
|
||||||
|
$request = new HTTPRequest('GET', '/');
|
||||||
|
$request->setSession($session);
|
||||||
|
$delegate = function () {
|
||||||
|
// noop
|
||||||
|
};
|
||||||
|
$middleware->process($request, $delegate);
|
||||||
|
|
||||||
|
Injector::unnest();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user