From 495145df6134b364b397ace85f42db74dc7dc348 Mon Sep 17 00:00:00 2001
From: Deltik <deltik@gmx.com>
Date: Fri, 9 Feb 2018 06:45:23 -0600
Subject: [PATCH] Added automatic database support to all suites

Refactored by extracting code common to all suites to \Helper\Base

New \Helper\DelayedDb helper to delay initialization so that a new DSN,
username, and password can be loaded in dynamically for automatic
database provisioning.  Should still be compatible with manual database
information in codeception.yml
---
 README.md                            |  2 +-
 codeception.yml                      |  6 +++
 e107                                 |  2 +-
 lib/deployers/cpanel_deployer.php    | 21 ++++++++++-
 tests/_support/Helper/Acceptance.php | 19 ++--------
 tests/_support/Helper/Base.php       | 56 ++++++++++++++++++++++++++++
 tests/_support/Helper/DelayedDb.php  | 20 ++++++++++
 7 files changed, 108 insertions(+), 18 deletions(-)
 create mode 100644 tests/_support/Helper/Base.php
 create mode 100644 tests/_support/Helper/DelayedDb.php

diff --git a/README.md b/README.md
index 21f45021c..dc42b7030 100644
--- a/README.md
+++ b/README.md
@@ -48,4 +48,4 @@ If you do not have a cPanel account that meets the requirements, you can run acc
 4. Grant the MySQL/MariaDB user `ALL PRIVILEGES` on the MySQL/MariaDB database.
 5. Put the app on the web server and note its URL.
 6. Write the URL to `tests/acceptance.suite.yml` in your copy of this repository where the `url` setting for the `PhpBrowser` module is.
-7. **TODO:** Manual database credentials are not supported yet.
+7. Write the database configuration to `codeception.yml` in your copy of this repository under the `\Helper\DelayedDb` module.
diff --git a/codeception.yml b/codeception.yml
index fedfce8d5..41566e860 100644
--- a/codeception.yml
+++ b/codeception.yml
@@ -12,3 +12,9 @@ params:
 extensions:
     enabled:
         - Codeception\Extension\RunFailed
+modules:
+    enabled:
+        - \Helper\DelayedDb:
+            dsn: 'mysql:host=set-this-if-running-tests-manually.local;dbname=e107'
+            user: 'root'
+            password: ''
diff --git a/e107 b/e107
index 986aabb06..e045c6c91 160000
--- a/e107
+++ b/e107
@@ -1 +1 @@
-Subproject commit 986aabb062762638258215d30957dc0984de0923
+Subproject commit e045c6c91c6fc8c8e760ff501a2a7fe6c10404d3
diff --git a/lib/deployers/cpanel_deployer.php b/lib/deployers/cpanel_deployer.php
index 4fbe892b5..59a249ac4 100644
--- a/lib/deployers/cpanel_deployer.php
+++ b/lib/deployers/cpanel_deployer.php
@@ -9,6 +9,8 @@ class cPanelDeployer
 	protected $cPanel;
 	protected $run_id;
 
+	protected $db_id;
+
 	protected $homedir;
 	protected $docroot;
 	protected $domain;
@@ -27,6 +29,23 @@ class cPanelDeployer
 		return "http://".$this->domain."/".$this->run_id."/";
 	}
 
+	public function getDsn()
+	{
+		$hostname = $this->credentials['hostname'];
+		$db_id = $this->db_id;
+		return "mysql:host=${hostname};dbname=${db_id}";
+	}
+
+	public function getDbUsername()
+	{
+		return $this->db_id;
+	}
+
+	public function getDbPassword()
+	{
+		return $this->run_id;
+	}
+
         public function start($components = self::DEFAULT_COMPONENTS)
         {
 		self::println();
@@ -124,7 +143,7 @@ class cPanelDeployer
 		$cPanel = $this->cPanel;
 		$username = &$this->credentials['username'];
 		$run_id = &$this->run_id;
-		$db_id = "${username}_${run_id}";
+		$this->db_id = $db_id = "${username}_${run_id}";
 		self::println("Creating new MySQL database \"${db_id}\"…");
 		$cPanel->uapi->Mysql->create_database(['name' => $db_id]);
 
diff --git a/tests/_support/Helper/Acceptance.php b/tests/_support/Helper/Acceptance.php
index 773ed6aec..b8dc9f083 100644
--- a/tests/_support/Helper/Acceptance.php
+++ b/tests/_support/Helper/Acceptance.php
@@ -1,31 +1,20 @@
 <?php
 namespace Helper;
-include_once(__DIR__ . "/../../../lib/deployers/cpanel_deployer.php");
 
 // here you can define custom actions
 // all public methods declared in helper class will be available in $I
 
-class Acceptance extends \Codeception\Module
+class Acceptance extends Base
 {
-	protected $deployer;
+	protected $deployer_components = ['db', 'fs'];
 
 	public function _beforeSuite($settings = array())
 	{
-		$secrets = $settings['secrets'];
-		if ($secrets['cpanel']['enabled'] === '1')
-		{
-			$this->deployer = new \cPanelDeployer($secrets['cpanel']);
-			$retcode = $this->deployer->start();
-			if ($retcode === true)
-			{
-				$url = $this->deployer->getUrl();
-		   		$this->getModule('PhpBrowser')->_reconfigure(array('url' => $url));
-			}
-		}
+		return parent::_beforeSuite($settings);
 	}
 
 	public function _afterSuite()
 	{
-		$this->deployer->stop();
+		return parent::_afterSuite();
 	}
 }
diff --git a/tests/_support/Helper/Base.php b/tests/_support/Helper/Base.php
new file mode 100644
index 000000000..bcbc2fa6e
--- /dev/null
+++ b/tests/_support/Helper/Base.php
@@ -0,0 +1,56 @@
+<?php
+namespace Helper;
+include_once(__DIR__ . "/../../../lib/deployers/cpanel_deployer.php");
+
+// here you can define custom actions
+// all public methods declared in helper class will be available in $I
+
+abstract class Base extends \Codeception\Module
+{
+        protected $deployer;
+        protected $deployer_components = ['db', 'fs'];
+
+	public function _beforeSuite($settings = array())
+	{
+		$secrets = $settings['secrets'];
+		if ($secrets['cpanel']['enabled'] === '1')
+		{
+			$this->deployer = new \cPanelDeployer($secrets['cpanel']);
+			$retcode = $this->deployer->start($this->deployer_components);
+			if ($retcode === true)
+			{
+                                $this->_callbackDeployerStarted();
+			}
+		}
+	}
+
+        public function _afterSuite()
+        {
+		$this->deployer->stop();
+        }
+
+        protected function _callbackDeployerStarted()
+        {
+                foreach ($this->deployer_components as $component)
+                {
+                        $method = "_reconfigure_${component}";
+                        $this->$method();
+                }
+        }
+
+        protected function _reconfigure_fs()
+        {
+		$url = $this->deployer->getUrl();
+		$this->getModule('PhpBrowser')->_reconfigure(array('url' => $url));
+        }
+
+        protected function _reconfigure_db()
+        {
+		$Db_config = array();
+		$Db_config['dsn'] = $this->deployer->getDsn();
+		$Db_config['user'] = $this->deployer->getDbUsername();
+		$Db_config['password'] = $this->deployer->getDbPassword();
+		$this->getModule('\Helper\DelayedDb')->_reconfigure($Db_config);
+		$this->getModule('\Helper\DelayedDb')->_delayedInitialize();
+        }
+}
diff --git a/tests/_support/Helper/DelayedDb.php b/tests/_support/Helper/DelayedDb.php
new file mode 100644
index 000000000..09d47ee0c
--- /dev/null
+++ b/tests/_support/Helper/DelayedDb.php
@@ -0,0 +1,20 @@
+<?php
+namespace Helper;
+
+// here you can define custom actions
+// all public methods declared in helper class will be available in $I
+
+class DelayedDb extends \Codeception\Module\Db
+{
+	protected $requiredFields = [];
+
+	public function _initialize()
+	{
+		// Noop
+	}
+
+	public function _delayedInitialize()
+	{
+		return parent::_initialize();
+	}
+}