diff --git a/README.md b/README.md index 9f30fc0..db9283b 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ This module starts a testing session in a browser, in order to test a SilverStripe application in a clean state. Usually the session is started on a fresh database with only default records loaded. -Further data can be loaded from YAML fixtures. +Further data can be loaded from YAML fixtures or database dumps. The module also serves as an initializer for the [SilverStripe Behat Extension](https://github.com/silverstripe-labs/silverstripe-behat-extension/). @@ -47,6 +47,7 @@ Parameters for "dev/testsession/start": (see [fixture format docs](http://doc.silverstripe.org/framework/en/topics/testing/fixtures)). The path should be relative to the webroot. * `createDatabase`: Create a temporary database. + * `createDatabaseTemplate`: Path to a database dump to load into a newly created temporary database. * `database`: Set an alternative database name in the current browser session as a cookie. Does not actually create the database, that's usually handled by `SapphireTest::create_temp_db()`. diff --git a/code/TestSessionController.php b/code/TestSessionController.php index 266022a..c6b199f 100644 --- a/code/TestSessionController.php +++ b/code/TestSessionController.php @@ -16,6 +16,11 @@ class TestSessionController extends Controller { private static $alternative_database_name = -1; + /** + * @var String Absolute path to a folder containing *.sql dumps. + */ + private static $database_templates_path; + public function init() { parent::init(); @@ -24,6 +29,9 @@ class TestSessionController extends Controller { && (Director::isDev() || Director::isTest() || Director::is_cli() || Permission::check("ADMIN")) ); if(!$canAccess) return Security::permissionFailure($this); + + Requirements::javascript('framework/thirdparty/jquery/jquery.js'); + Requirements::javascript('testsession/javascript/testsession.js'); } public function Link($action = null) { @@ -51,9 +59,17 @@ class TestSessionController extends Controller { } public function StartForm() { + $databaseTemplates = $this->getDatabaseTemplates(); $fields = new FieldList( new CheckboxField('createDatabase', 'Create temporary database?', 1) ); + if($databaseTemplates) { + $fields->push( + (new DropdownField('createDatabaseTemplate', false)) + ->setSource($databaseTemplates) + ->setEmptyString('Empty database') + ); + } $fields->merge($this->getBaseFields()); $form = new Form( $this, @@ -252,6 +268,27 @@ class TestSessionController extends Controller { global $databaseConfig; DB::connect(array_merge($databaseConfig, array('database' => $dbName))); if(isset($data['database'])) unset($data['database']); + + // Import database template if required + if(isset($data['createDatabaseTemplate']) && $data['createDatabaseTemplate']) { + $sql = file_get_contents($data['createDatabaseTemplate']); + // Split into individual query commands, removing comments + $sqlCmds = array_filter( + preg_split('/\s*;\s*/', + preg_replace(array('/^$\n/m', '/^(\/|#).*$\n/m'), '', $sql) + ) + ); + + // Execute each query + foreach($sqlCmds as $sqlCmd) { + DB::query($sqlCmd); + } + + // In case the dump involved CREATE TABLE commands, we need to ensure + // the schema is still up to date + $dbAdmin = new DatabaseAdmin(); + $dbAdmin->doBuild(true /*quiet*/, false /*populate*/); + } } // Fixtures @@ -321,4 +358,34 @@ class TestSessionController extends Controller { return new ArrayList($state); } + /** + * Get all *.sql database files located in a specific path, + * keyed by their file name. + * + * @param String $path Absolute folder path + * @return array + */ + protected function getDatabaseTemplates($path = null) { + $templates = array(); + + if(!$path) { + $path = $this->config()->database_templates_path; + } + + // TODO Remove once we can set BASE_PATH through the config layer + if($path && !Director::is_absolute($path)) { + $path = BASE_PATH . '/' . $path; + } + + if($path && file_exists($path)) { + $it = new FilesystemIterator($path); + foreach($it as $fileinfo) { + if($fileinfo->getExtension() != 'sql') continue; + $templates[$fileinfo->getRealPath()] = $fileinfo->getFilename(); + } + } + + return $templates; + } + } \ No newline at end of file diff --git a/javascript/testsession.js b/javascript/testsession.js new file mode 100644 index 0000000..c36dc6e --- /dev/null +++ b/javascript/testsession.js @@ -0,0 +1,11 @@ +(function($) { + $(document).ready(function() { + // Only show database templates when "create database" is selected + var tmplField = $('#createDatabaseTemplate'), + createField = $('#createDatabase input'), + toggleFn = function() {tmplField.toggle(createField.is(':checked'));}; + + toggleFn(); + createField.click(toggleFn); + }); +}(jQuery)); \ No newline at end of file