mirror of
https://github.com/silverstripe/silverstripe-testsession
synced 2024-10-22 14:06:00 +02:00
ADD / TestSessionState initial implementation
TestSessionState model initial implementation TestSessionEnvironment to initialize the state for every scenario and provide API for the clients to use it TestSessionHTTPMiddleware to keep the state fields up to date
This commit is contained in:
parent
961069473c
commit
78dd43ed96
@ -20,6 +20,11 @@ is a random token stored in the browser session, in order to make the
|
|||||||
test session specific to the executing browser, and allow multiple
|
test session specific to the executing browser, and allow multiple
|
||||||
people using their own test session in the same webroot.
|
people using their own test session in the same webroot.
|
||||||
|
|
||||||
|
The module also keeps some metadata about the session state in the database,
|
||||||
|
so that it may be available for the clients as well.
|
||||||
|
E.g. the silverstripe-behat-extension may use it through this module APIs,
|
||||||
|
allowing us to introduce some grey-box testing techniques.
|
||||||
|
|
||||||
The module also serves as an initializer for the
|
The module also serves as an initializer for the
|
||||||
[SilverStripe Behat Extension](https://github.com/silverstripe-labs/silverstripe-behat-extension/).
|
[SilverStripe Behat Extension](https://github.com/silverstripe-labs/silverstripe-behat-extension/).
|
||||||
It is required for Behat because the Behat CLI test runner needs to persist
|
It is required for Behat because the Behat CLI test runner needs to persist
|
||||||
|
@ -335,6 +335,8 @@ class TestSessionEnvironment
|
|||||||
// Connect to the new database, overwriting the old DB connection (if any)
|
// Connect to the new database, overwriting the old DB connection (if any)
|
||||||
DB::connect($databaseConfig);
|
DB::connect($databaseConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestSessionState::create()->write(); // initialize the session state
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mailer
|
// Mailer
|
||||||
@ -363,6 +365,7 @@ class TestSessionEnvironment
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->saveState($state);
|
$this->saveState($state);
|
||||||
|
|
||||||
$this->extend('onAfterApplyState');
|
$this->extend('onAfterApplyState');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -558,4 +561,34 @@ class TestSessionEnvironment
|
|||||||
{
|
{
|
||||||
return PUBLIC_PATH . DIRECTORY_SEPARATOR . 'assets_backup';
|
return PUBLIC_PATH . DIRECTORY_SEPARATOR . 'assets_backup';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for pending requests
|
||||||
|
*
|
||||||
|
* @param int $await Time to wait (in ms) after the last response (to allow the browser react)
|
||||||
|
* @param int $timeout For how long (in ms) do we wait before giving up
|
||||||
|
*
|
||||||
|
* @return bool Whether there are no more pending requests
|
||||||
|
*/
|
||||||
|
public function waitForPendingRequests($await=700, $timeout=10000)
|
||||||
|
{
|
||||||
|
$timeout = microtime(true) * 10000 + $timeout;
|
||||||
|
$interval = $await < 300 ? 300 : $await;
|
||||||
|
do {
|
||||||
|
$model = TestSessionState::get()->byID(1);
|
||||||
|
|
||||||
|
$pendingRequests = $model->PendingRequests > 0;
|
||||||
|
$lastRequestAwait = $model->LastResponseTimestamp + $await > microtime(true) * 10000;
|
||||||
|
|
||||||
|
$pending = $pendingRequests || $lastRequestAwait;
|
||||||
|
|
||||||
|
if ($timeout < microtime(true) * 10000) {
|
||||||
|
// timed out
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} while ($pending && (usleep($interval * 1000) || true));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,10 @@ use SilverStripe\Control\Email\Mailer;
|
|||||||
use SilverStripe\Control\HTTPRequest;
|
use SilverStripe\Control\HTTPRequest;
|
||||||
use SilverStripe\Control\Middleware\HTTPMiddleware;
|
use SilverStripe\Control\Middleware\HTTPMiddleware;
|
||||||
use SilverStripe\Core\Injector\Injector;
|
use SilverStripe\Core\Injector\Injector;
|
||||||
|
use SilverStripe\ORM\DataObject;
|
||||||
use SilverStripe\ORM\DB;
|
use SilverStripe\ORM\DB;
|
||||||
use SilverStripe\ORM\FieldType\DBDatetime;
|
use SilverStripe\ORM\FieldType\DBDatetime;
|
||||||
|
use SilverStripe\ORM\Queries\SQLUpdate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets state previously initialized through {@link TestSessionController}.
|
* Sets state previously initialized through {@link TestSessionController}.
|
||||||
@ -39,15 +41,42 @@ class TestSessionHTTPMiddleware implements HTTPMiddleware
|
|||||||
|
|
||||||
// Load test state
|
// Load test state
|
||||||
$this->loadTestState($request);
|
$this->loadTestState($request);
|
||||||
|
$this->incrementModelState();
|
||||||
|
|
||||||
// Call with safe teardown
|
// Call with safe teardown
|
||||||
try {
|
try {
|
||||||
return $delegate($request);
|
return $delegate($request);
|
||||||
} finally {
|
} finally {
|
||||||
$this->restoreTestState($request);
|
$this->restoreTestState($request);
|
||||||
|
$this->decrementModelState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function incrementModelState() {
|
||||||
|
$schema = DataObject::getSchema();
|
||||||
|
|
||||||
|
$update = SQLUpdate::create(sprintf('"%s"', $schema->tableName(TestSessionState::class)))
|
||||||
|
->addWhere(['ID' => 1])
|
||||||
|
->addAssignments([
|
||||||
|
'PendingRequests' => [ '"PendingRequests" + 1' => [] ]
|
||||||
|
]);
|
||||||
|
|
||||||
|
$update->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function decrementModelState() {
|
||||||
|
$schema = DataObject::getSchema();
|
||||||
|
|
||||||
|
$update = SQLUpdate::create(sprintf('"%s"', $schema->tableName(TestSessionState::class)))
|
||||||
|
->addWhere(['ID' => 1])
|
||||||
|
->addAssignments([
|
||||||
|
'"PendingRequests"' => [ '"PendingRequests" - 1' => [] ],
|
||||||
|
'"LastResponseTimestamp"' => microtime(true) * 10000
|
||||||
|
]);
|
||||||
|
|
||||||
|
$update->execute();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load test state from environment into "real" environment
|
* Load test state from environment into "real" environment
|
||||||
*
|
*
|
||||||
|
33
src/TestSessionState.php
Normal file
33
src/TestSessionState.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\TestSession;
|
||||||
|
|
||||||
|
use SilverStripe\ORM\DataObject;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The session state keeps some metadata about the current test session.
|
||||||
|
* This may allow the client (Behat) to get some insight into the
|
||||||
|
* server side affairs (e.g. if the server is handling some number requests at the moment).
|
||||||
|
*
|
||||||
|
* The client side (Behat) must not use this class straightforwardly, but rather
|
||||||
|
* rely on the API of {@see TestSessionEnvironment} or {@see TestSessionController}.
|
||||||
|
*/
|
||||||
|
class TestSessionState extends DataObject
|
||||||
|
{
|
||||||
|
private static $db = [
|
||||||
|
/**
|
||||||
|
* Pending requests to keep information
|
||||||
|
* about how many requests are in progress
|
||||||
|
* on the server
|
||||||
|
*/
|
||||||
|
'PendingRequests' => 'Int',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The microtime stamp of the last response
|
||||||
|
* made by the server.
|
||||||
|
* (well, actually that's rather TestSessionMiddleware)
|
||||||
|
*/
|
||||||
|
'LastResponseTimestamp' => 'Decimal(14, 0)'
|
||||||
|
];
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user