From d4b36e9bad4c9d64447f053ec19a9f600888b2fe Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Sun, 14 Jan 2018 01:48:50 +0100 Subject: Added Illuminate/Database --- .../Unit/Database/DatabaseServiceProviderTest.php | 8 ++-- tests/Unit/Database/DbTest.php | 43 ++++++++++++++++++---- 2 files changed, 39 insertions(+), 12 deletions(-) (limited to 'tests/Unit/Database') diff --git a/tests/Unit/Database/DatabaseServiceProviderTest.php b/tests/Unit/Database/DatabaseServiceProviderTest.php index 61848c35..911af399 100644 --- a/tests/Unit/Database/DatabaseServiceProviderTest.php +++ b/tests/Unit/Database/DatabaseServiceProviderTest.php @@ -24,10 +24,10 @@ class DatabaseServiceProviderTest extends ServiceProviderTest $this->setExpects($app, 'get', ['config'], $config); $this->setExpects($config, 'get', ['database'], [ - 'host' => 'localhost', - 'db' => 'database', - 'user' => 'user', - 'pw' => 'password', + 'host' => 'localhost', + 'database' => 'database', + 'username' => 'user', + 'password' => 'password', ], $this->atLeastOnce()); $this->expectException(Exception::class); diff --git a/tests/Unit/Database/DbTest.php b/tests/Unit/Database/DbTest.php index 63607cad..17829e77 100644 --- a/tests/Unit/Database/DbTest.php +++ b/tests/Unit/Database/DbTest.php @@ -3,24 +3,46 @@ namespace Engelsystem\Test\Unit\Database; use Engelsystem\Database\Db; +use Illuminate\Database\Capsule\Manager as CapsuleManager; +use Illuminate\Database\Connection as DatabaseConnection; use PDO; use PDOStatement; use PHPUnit\Framework\TestCase; +use PHPUnit_Framework_MockObject_MockObject as MockObject; use ReflectionObject; use Throwable; class DbTest extends TestCase { /** - * @covers \Engelsystem\Database\Db::connect() + * @covers \Engelsystem\Database\Db::setDbManager() */ - public function testConnect() + public function testSetDbManager() { - $result = Db::connect('mysql:host=localhost;dbname=someTestDatabaseThatDoesNotExist;charset=utf8'); - $this->assertFalse($result); - - $result = Db::connect('sqlite::memory:'); - $this->assertTrue($result); + /** @var MockObject|Pdo $pdo */ + $pdo = $this->getMockBuilder(Pdo::class) + ->disableOriginalConstructor() + ->getMock(); + /** @var MockObject|CapsuleManager $dbManager */ + $dbManager = $this->getMockBuilder(CapsuleManager::class) + ->disableOriginalConstructor() + ->getMock(); + /** @var MockObject|DatabaseConnection $dbManager */ + $databaseConnection = $this->getMockBuilder(DatabaseConnection::class) + ->disableOriginalConstructor() + ->getMock(); + + $dbManager + ->expects($this->atLeastOnce()) + ->method('getConnection') + ->willReturn($databaseConnection); + $databaseConnection + ->expects($this->atLeastOnce()) + ->method('getPdo') + ->willReturn($pdo); + + Db::setDbManager($dbManager); + $this->assertEquals($pdo, Db::getPdo()); } /** @@ -167,7 +189,12 @@ class DbTest extends TestCase */ protected function setUp() { - Db::connect('sqlite::memory:'); + $dbManager = new CapsuleManager(); + $dbManager->addConnection(['driver' => 'sqlite', 'database' => ':memory:']); + $dbManager->setAsGlobal(); + $dbManager->bootEloquent(); + + Db::setDbManager($dbManager); Db::getPdo()->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); Db::query( ' -- cgit v1.2.3-54-g00ecf From 0e8cc2f0a73085170df45c6a40e8f3df06a6af51 Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Sun, 14 Jan 2018 13:32:57 +0100 Subject: database: integrated illuminate/database do Db class, removed unused methods --- includes/model/EventConfig_model.php | 4 +- includes/model/LogEntries_model.php | 2 +- src/Database/Db.php | 99 +++++++----------------------------- tests/Unit/Database/DbTest.php | 82 +++-------------------------- 4 files changed, 26 insertions(+), 161 deletions(-) (limited to 'tests/Unit/Database') diff --git a/includes/model/EventConfig_model.php b/includes/model/EventConfig_model.php index 646d19c5..8a29482b 100644 --- a/includes/model/EventConfig_model.php +++ b/includes/model/EventConfig_model.php @@ -21,7 +21,7 @@ function EventConfig() * @param int $event_end_date * @param int $teardown_end_date * @param string $event_welcome_msg - * @return int Rows updated + * @return bool */ function EventConfig_update( $event_name, @@ -54,7 +54,7 @@ function EventConfig_update( ); } - return DB::update(' + return (bool)DB::update(' UPDATE `EventConfig` SET `event_name` = ?, `buildup_start_date` = ?, diff --git a/includes/model/LogEntries_model.php b/includes/model/LogEntries_model.php index f0ee6673..b16c598c 100644 --- a/includes/model/LogEntries_model.php +++ b/includes/model/LogEntries_model.php @@ -58,5 +58,5 @@ function LogEntries_filter($keyword) */ function LogEntries_clear_all() { - return DB::statement('TRUNCATE `LogEntries`'); + return DB::connection()->statement('TRUNCATE `LogEntries`'); } diff --git a/src/Database/Db.php b/src/Database/Db.php index aa9b1a27..426dd526 100644 --- a/src/Database/Db.php +++ b/src/Database/Db.php @@ -3,20 +3,14 @@ namespace Engelsystem\Database; use Illuminate\Database\Capsule\Manager as CapsuleManager; +use Illuminate\Database\Connection as DatabaseConnection; use PDO; -use PDOStatement; class Db { /** @var CapsuleManager */ protected static $dbManager; - /** @var PDOStatement */ - protected static $stm = null; - - /** @var bool */ - protected static $lastStatus = true; - /** * Set the database connection manager * @@ -27,35 +21,6 @@ class Db self::$dbManager = $dbManager; } - /** - * Run a prepared query - * - * @param string $query - * @param array $bindings - * @return PDOStatement - */ - public static function query($query, array $bindings = []) - { - self::$stm = self::getPdo()->prepare($query); - self::$lastStatus = self::$stm->execute($bindings); - - return self::$stm; - } - - /** - * Run a sql query - * - * @param string $query - * @return bool - */ - public static function unprepared($query) - { - self::$stm = self::getPdo()->query($query); - self::$lastStatus = (self::$stm instanceof PDOStatement); - - return self::$lastStatus; - } - /** * Run a select query * @@ -65,9 +30,13 @@ class Db */ public static function select($query, array $bindings = []) { - self::query($query, $bindings); + $return = self::connection()->select($query, $bindings); + + foreach ($return as $key => $value) { + $return[$key] = (array)$value; + } - return self::$stm->fetchAll(PDO::FETCH_ASSOC); + return $return; } /** @@ -79,13 +48,13 @@ class Db */ public static function selectOne($query, array $bindings = []) { - $result = self::select($query, $bindings); + $result = self::connection()->selectOne($query, $bindings); if (empty($result)) { return null; } - return array_shift($result); + return (array)$result; } /** @@ -93,13 +62,11 @@ class Db * * @param string $query * @param array $bindings - * @return int Row count + * @return bool */ public static function insert($query, array $bindings = []) { - self::query($query, $bindings); - - return self::$stm->rowCount(); + return self::connection()->insert($query, $bindings); } /** @@ -111,9 +78,7 @@ class Db */ public static function update($query, array $bindings = []) { - self::query($query, $bindings); - - return self::$stm->rowCount(); + return self::connection()->update($query, $bindings); } /** @@ -125,37 +90,15 @@ class Db */ public static function delete($query, array $bindings = []) { - self::query($query, $bindings); - - return self::$stm->rowCount(); - } - - /** - * Run a single statement - * - * @param string $query - * @param array $bindings - * @return bool - */ - public static function statement($query, array $bindings = []) - { - self::query($query, $bindings); - - return self::$lastStatus; + return self::connection()->delete($query, $bindings); } /** - * Returns the last error - * - * @return array + * @return DatabaseConnection */ - public static function getError() + public static function connection() { - if (!self::$stm instanceof PDOStatement) { - return [-1, null, null]; - } - - return self::$stm->errorInfo(); + return self::$dbManager->getConnection(); } /** @@ -165,14 +108,6 @@ class Db */ public static function getPdo() { - return self::$dbManager->getConnection()->getPdo(); - } - - /** - * @return PDOStatement|false|null - */ - public static function getStm() - { - return self::$stm; + return self::connection()->getPdo(); } } diff --git a/tests/Unit/Database/DbTest.php b/tests/Unit/Database/DbTest.php index 17829e77..ca6ac52c 100644 --- a/tests/Unit/Database/DbTest.php +++ b/tests/Unit/Database/DbTest.php @@ -6,16 +6,14 @@ use Engelsystem\Database\Db; use Illuminate\Database\Capsule\Manager as CapsuleManager; use Illuminate\Database\Connection as DatabaseConnection; use PDO; -use PDOStatement; use PHPUnit\Framework\TestCase; use PHPUnit_Framework_MockObject_MockObject as MockObject; -use ReflectionObject; -use Throwable; class DbTest extends TestCase { /** * @covers \Engelsystem\Database\Db::setDbManager() + * @covers \Engelsystem\Database\Db::connection() */ public function testSetDbManager() { @@ -43,27 +41,7 @@ class DbTest extends TestCase Db::setDbManager($dbManager); $this->assertEquals($pdo, Db::getPdo()); - } - - /** - * @covers \Engelsystem\Database\Db::query() - */ - public function testQuery() - { - $stm = Db::query('SELECT * FROM test_data'); - $this->assertEquals('00000', $stm->errorCode()); - - $stm = Db::query('SELECT * FROM test_data WHERE id = ?', [4]); - $this->assertEquals('00000', $stm->errorCode()); - } - - /** - * @covers \Engelsystem\Database\Db::unprepared() - */ - public function testUnprepared() - { - $return = Db::unprepared('SELECT * FROM test_data WHERE id = 3'); - $this->assertTrue($return); + $this->assertEquals($databaseConnection, Db::connection()); } /** @@ -99,11 +77,8 @@ class DbTest extends TestCase */ public function testInsert() { - $count = Db::insert("INSERT INTO test_data (id, data) VALUES (5, 'Some random text'), (6, 'another text')"); - $this->assertEquals(2, $count); - - $count = Db::insert('INSERT INTO test_data(id, data) VALUES (:id, :alias)', ['id' => 7, 'alias' => 'Blafoo']); - $this->assertEquals(1, $count); + $result = Db::insert("INSERT INTO test_data (id, data) VALUES (5, 'Some random text'), (6, 'another text')"); + $this->assertTrue($result); } /** @@ -130,42 +105,6 @@ class DbTest extends TestCase $this->assertEquals(3, $count); } - /** - * @covers \Engelsystem\Database\Db::statement() - */ - public function testStatement() - { - $return = Db::statement('SELECT * FROM test_data WHERE id = 3'); - $this->assertTrue($return); - - $return = Db::statement('SELECT * FROM test_data WHERE id = ?', [2]); - $this->assertTrue($return); - } - - /** - * @covers \Engelsystem\Database\Db::getError() - */ - public function testGetError() - { - try { - Db::statement('foo'); - } catch (Throwable $e) { - } - - $error = Db::getError(); - $this->assertTrue(is_array($error)); - $this->assertEquals('near "foo": syntax error', $error[2]); - - $db = new Db(); - $refObject = new ReflectionObject($db); - $refProperty = $refObject->getProperty('stm'); - $refProperty->setAccessible(true); - $refProperty->setValue(null, null); - - $error = Db::getError(); - $this->assertEquals([-1, null, null], $error); - } - /** * @covers \Engelsystem\Database\Db::getPdo() */ @@ -175,15 +114,6 @@ class DbTest extends TestCase $this->assertInstanceOf(PDO::class, $pdo); } - /** - * @covers \Engelsystem\Database\Db::getStm() - */ - public function testGetStm() - { - $stm = Db::getStm(); - $this->assertInstanceOf(PDOStatement::class, $stm); - } - /** * Setup in memory database */ @@ -196,14 +126,14 @@ class DbTest extends TestCase Db::setDbManager($dbManager); Db::getPdo()->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - Db::query( + Db::connection()->statement( ' CREATE TABLE test_data( id INT PRIMARY KEY NOT NULL, data TEXT NOT NULL ); '); - Db::query('CREATE UNIQUE INDEX test_data_id_uindex ON test_data (id);'); + Db::connection()->statement('CREATE UNIQUE INDEX test_data_id_uindex ON test_data (id);'); Db::insert(" INSERT INTO test_data (id, data) VALUES -- cgit v1.2.3-54-g00ecf From 78cddecef3ed0e29445a699ef7e6df56352779a4 Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Mon, 15 Jan 2018 23:31:19 +0100 Subject: DatabaseServiceProvider: Added unit tests --- src/Database/DatabaseServiceProvider.php | 4 +- .../Unit/Database/DatabaseServiceProviderTest.php | 71 +++++++++++++++++++--- 2 files changed, 64 insertions(+), 11 deletions(-) (limited to 'tests/Unit/Database') diff --git a/src/Database/DatabaseServiceProvider.php b/src/Database/DatabaseServiceProvider.php index 306ffaca..818b76c4 100644 --- a/src/Database/DatabaseServiceProvider.php +++ b/src/Database/DatabaseServiceProvider.php @@ -5,7 +5,7 @@ namespace Engelsystem\Database; use Engelsystem\Container\ServiceProvider; use Exception; use Illuminate\Database\Capsule\Manager as CapsuleManager; -use Illuminate\Events\Dispatcher as EventsDispatcher; +use PDOException; class DatabaseServiceProvider extends ServiceProvider { @@ -31,7 +31,7 @@ class DatabaseServiceProvider extends ServiceProvider try { $capsule->getConnection()->getPdo(); - } catch (\PDOException $e) { + } catch (PDOException $e) { $this->exitOnError(); } diff --git a/tests/Unit/Database/DatabaseServiceProviderTest.php b/tests/Unit/Database/DatabaseServiceProviderTest.php index 911af399..2e05d27f 100644 --- a/tests/Unit/Database/DatabaseServiceProviderTest.php +++ b/tests/Unit/Database/DatabaseServiceProviderTest.php @@ -6,32 +6,85 @@ use Engelsystem\Config\Config; use Engelsystem\Database\DatabaseServiceProvider; use Engelsystem\Test\Unit\ServiceProviderTest; use Exception; -use PHPUnit_Framework_MockObject_MockObject; +use Illuminate\Database\Capsule\Manager as CapsuleManager; +use Illuminate\Database\Connection; +use PDOException; +use PHPUnit_Framework_MockObject_MockObject as MockObject; class DatabaseServiceProviderTest extends ServiceProviderTest { /** * @covers \Engelsystem\Database\DatabaseServiceProvider::register() - * @covers \Engelsystem\Database\DatabaseServiceProvider::exitOnError() */ public function testRegister() { - /** @var PHPUnit_Framework_MockObject_MockObject|Config $config */ - $config = $this->getMockBuilder(Config::class) - ->getMock(); + list($app, $dbManager) = $this->prepare(['driver' => 'sqlite', 'database' => ':memory:']); - $app = $this->getApp(['get']); + $this->setExpects($app, 'instance', ['db', $dbManager]); - $this->setExpects($app, 'get', ['config'], $config); - $this->setExpects($config, 'get', ['database'], [ + $serviceProvider = new DatabaseServiceProvider($app); + $serviceProvider->register(); + } + + /** + * @covers \Engelsystem\Database\DatabaseServiceProvider::register() + * @covers \Engelsystem\Database\DatabaseServiceProvider::exitOnError() + */ + public function testRegisterError() + { + list($app) = $this->prepare([ 'host' => 'localhost', 'database' => 'database', 'username' => 'user', 'password' => 'password', - ], $this->atLeastOnce()); + ], true); + $this->expectException(Exception::class); $serviceProvider = new DatabaseServiceProvider($app); $serviceProvider->register(); } + + /** + * Prepare some mocks + * + * @param array $dbConfigData + * @param bool $getPdoThrowException + * @return array + */ + protected function prepare($dbConfigData, $getPdoThrowException = false) + { + /** @var MockObject|Config $config */ + $config = $this->getMockBuilder(Config::class) + ->getMock(); + /** @var MockObject|CapsuleManager $config */ + $dbManager = $this->getMockBuilder(CapsuleManager::class) + ->getMock(); + /** @var MockObject|Connection $connection */ + $connection = $this->getMockBuilder(Connection::class) + ->disableOriginalConstructor() + ->getMock(); + + $app = $this->getApp(['get', 'make', 'instance']); + + $this->setExpects($app, 'get', ['config'], $config); + $this->setExpects($app, 'make', [CapsuleManager::class], $dbManager); + $this->setExpects($config, 'get', ['database'], $dbConfigData, $this->atLeastOnce()); + + $this->setExpects($dbManager, 'setAsGlobal'); + $this->setExpects($dbManager, 'bootEloquent'); + + $connection->expects($this->once()) + ->method('getPdo') + ->willReturnCallback(function () use ($getPdoThrowException) { + if ($getPdoThrowException) { + throw new PDOException(); + } + + return ''; + }); + $this->setExpects($dbManager, 'getConnection', [], $connection, $this->atLeastOnce()); + + return [$app, $dbManager]; + } } -- cgit v1.2.3-54-g00ecf From 235266ec53f620d94a080ed7ae8e77eaef6dbb3c Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Tue, 16 Jan 2018 21:26:59 +0100 Subject: Added basic database migration functionality --- bin/migrate | 21 +++ src/Database/DatabaseServiceProvider.php | 1 + src/Database/Migration/Migrate.php | 192 +++++++++++++++++++++ src/Database/Migration/Migration.php | 16 ++ .../Migration/MigrationServiceProvider.php | 20 +++ .../Unit/Database/DatabaseServiceProviderTest.php | 1 + tests/Unit/Database/Migration/MigrateTest.php | 160 +++++++++++++++++ .../Migration/MigrationServiceProviderTest.php | 55 ++++++ tests/Unit/Database/Migration/MigrationTest.php | 24 +++ .../2001_04_11_123456_create_lorem_ipsum_table.php | 27 +++ .../Stub/2017_12_24_053300_another_stuff.php | 22 +++ .../Stub/2022_12_22_221222_add_some_feature.php | 22 +++ 12 files changed, 561 insertions(+) create mode 100755 bin/migrate create mode 100644 src/Database/Migration/Migrate.php create mode 100644 src/Database/Migration/Migration.php create mode 100644 src/Database/Migration/MigrationServiceProvider.php create mode 100644 tests/Unit/Database/Migration/MigrateTest.php create mode 100644 tests/Unit/Database/Migration/MigrationServiceProviderTest.php create mode 100644 tests/Unit/Database/Migration/MigrationTest.php create mode 100644 tests/Unit/Database/Migration/Stub/2001_04_11_123456_create_lorem_ipsum_table.php create mode 100644 tests/Unit/Database/Migration/Stub/2017_12_24_053300_another_stuff.php create mode 100644 tests/Unit/Database/Migration/Stub/2022_12_22_221222_add_some_feature.php (limited to 'tests/Unit/Database') diff --git a/bin/migrate b/bin/migrate new file mode 100755 index 00000000..20ae2a93 --- /dev/null +++ b/bin/migrate @@ -0,0 +1,21 @@ +#!/usr/bin/env php +register(MigrationServiceProvider::class); + +/** @var Migrate $migration */ +$migration = $app->get('db.migration'); +$migration->setOutput(function ($text) { echo $text . PHP_EOL; }); +$migration->run($baseDir, Migrate::UP); diff --git a/src/Database/DatabaseServiceProvider.php b/src/Database/DatabaseServiceProvider.php index 818b76c4..7328bc4e 100644 --- a/src/Database/DatabaseServiceProvider.php +++ b/src/Database/DatabaseServiceProvider.php @@ -28,6 +28,7 @@ class DatabaseServiceProvider extends ServiceProvider $capsule->setAsGlobal(); $capsule->bootEloquent(); + $capsule->getConnection()->useDefaultSchemaGrammar(); try { $capsule->getConnection()->getPdo(); diff --git a/src/Database/Migration/Migrate.php b/src/Database/Migration/Migrate.php new file mode 100644 index 00000000..3a08bb6e --- /dev/null +++ b/src/Database/Migration/Migrate.php @@ -0,0 +1,192 @@ +app = $app; + $this->scheme = $scheme; + $this->output = function () { }; + } + + /** + * Run a migration + * + * @param string $path + * @param string $type (up|down) + * @param bool $oneStep + */ + public function run($path, $type = self::UP, $oneStep = false) + { + $this->initMigration(); + $migrations = $this->getMigrations($path); + $migrated = $this->getMigrated(); + + if ($type == self::DOWN) { + $migrations = array_reverse($migrations, true); + } + + foreach ($migrations as $file => $migration) { + if ( + ($type == self::UP && $migrated->contains('migration', $migration)) + || ($type == self::DOWN && !$migrated->contains('migration', $migration)) + ) { + call_user_func($this->output, 'Skipping ' . $migration); + continue; + } + + call_user_func($this->output, 'Migrating ' . $migration . ' (' . $type . ')'); + + $this->migrate($file, $migration, $type); + $this->setMigrated($migration, $type); + + if ($oneStep) { + return; + } + } + } + + /** + * Get all migrated migrations + * + * @return Collection + */ + protected function getMigrated() + { + return $this->getTableQuery()->get(); + } + + /** + * Migrate a migration + * + * @param string $file + * @param string $migration + * @param string $type (up|down) + */ + protected function migrate($file, $migration, $type = self::UP) + { + require_once $file; + + $className = Str::studly(preg_replace('/\d+_/', '', $migration)); + /** @var Migration $class */ + $class = $this->app->make($className); + + if (method_exists($class, $type)) { + $class->{$type}(); + } + } + + /** + * Set a migration to migrated + * + * @param string $migration + * @param string $type (up|down) + */ + protected function setMigrated($migration, $type = self::UP) + { + $table = $this->getTableQuery(); + + if ($type == self::DOWN) { + $table->where(['migration' => $migration])->delete(); + return; + } + + $table->insert(['migration' => $migration]); + } + + /** + * Get a list of migration files + * + * @param string $dir + * @return array + */ + protected function getMigrations($dir) + { + $files = $this->getMigrationFiles($dir); + + $migrations = []; + foreach ($files as $dir) { + $name = str_replace('.php', '', basename($dir)); + $migrations[$dir] = $name; + } + + asort($migrations); + return $migrations; + } + + /** + * List all migration files from the given directory + * + * @param string $dir + * @return array + */ + protected function getMigrationFiles($dir) + { + return glob($dir . '/*_*.php'); + } + + /** + * Setup migration tables + */ + protected function initMigration() + { + if ($this->scheme->hasTable($this->table)) { + return; + } + + $this->scheme->create($this->table, function (Blueprint $table) { + $table->increments('id'); + $table->string('migration'); + }); + } + + /** + * Init a table query + * + * @return Builder + */ + protected function getTableQuery() + { + return $this->scheme->getConnection()->table($this->table); + } + + /** + * Set the output function + * + * @param callable $output + */ + public function setOutput(callable $output) + { + $this->output = $output; + } +} diff --git a/src/Database/Migration/Migration.php b/src/Database/Migration/Migration.php new file mode 100644 index 00000000..fcc57b82 --- /dev/null +++ b/src/Database/Migration/Migration.php @@ -0,0 +1,16 @@ +schema = $schemaBuilder; + } +} diff --git a/src/Database/Migration/MigrationServiceProvider.php b/src/Database/Migration/MigrationServiceProvider.php new file mode 100644 index 00000000..15d06eaf --- /dev/null +++ b/src/Database/Migration/MigrationServiceProvider.php @@ -0,0 +1,20 @@ +getSchemaBuilder(); + $this->app->instance('db.scheme', $schema); + $this->app->bind(SchemaBuilder::class, 'db.scheme'); + + $migration = $this->app->make(Migrate::class); + $this->app->instance('db.migration', $migration); + } +} diff --git a/tests/Unit/Database/DatabaseServiceProviderTest.php b/tests/Unit/Database/DatabaseServiceProviderTest.php index 2e05d27f..8f7898cd 100644 --- a/tests/Unit/Database/DatabaseServiceProviderTest.php +++ b/tests/Unit/Database/DatabaseServiceProviderTest.php @@ -74,6 +74,7 @@ class DatabaseServiceProviderTest extends ServiceProviderTest $this->setExpects($dbManager, 'setAsGlobal'); $this->setExpects($dbManager, 'bootEloquent'); + $this->setExpects($connection, 'useDefaultSchemaGrammar'); $connection->expects($this->once()) ->method('getPdo') ->willReturnCallback(function () use ($getPdoThrowException) { diff --git a/tests/Unit/Database/Migration/MigrateTest.php b/tests/Unit/Database/Migration/MigrateTest.php new file mode 100644 index 00000000..c88ad777 --- /dev/null +++ b/tests/Unit/Database/Migration/MigrateTest.php @@ -0,0 +1,160 @@ +getMockBuilder(Application::class) + ->setMethods(['instance']) + ->getMock(); + /** @var MockObject|SchemaBuilder $builder */ + $builder = $this->getMockBuilder(SchemaBuilder::class) + ->disableOriginalConstructor() + ->getMock(); + /** @var MockObject|Migrate $migration */ + $migration = $this->getMockBuilder(Migrate::class) + ->setConstructorArgs([$builder, $app]) + ->setMethods(['initMigration', 'getMigrationFiles', 'getMigrated', 'migrate', 'setMigrated']) + ->getMock(); + + $migration->expects($this->atLeastOnce()) + ->method('initMigration'); + $migration->expects($this->atLeastOnce()) + ->method('getMigrationFiles') + ->willReturn([ + 'foo/1234_01_23_123456_init_foo.php', + 'foo/9876_03_22_210000_random_hack.php', + 'foo/4567_11_01_000000_do_stuff.php', + 'foo/9999_99_99_999999_another_foo.php', + ]); + $migration->expects($this->atLeastOnce()) + ->method('getMigrated') + ->willReturn(new Collection([ + ['id' => 1, 'migration' => '1234_01_23_123456_init_foo'], + ['id' => 2, 'migration' => '4567_11_01_000000_do_stuff'], + ])); + $migration->expects($this->atLeastOnce()) + ->method('migrate') + ->withConsecutive( + ['foo/9876_03_22_210000_random_hack.php', '9876_03_22_210000_random_hack', Migrate::UP], + ['foo/9999_99_99_999999_another_foo.php', '9999_99_99_999999_another_foo', Migrate::UP], + ['foo/9876_03_22_210000_random_hack.php', '9876_03_22_210000_random_hack', Migrate::UP], + ['foo/4567_11_01_000000_do_stuff.php', '4567_11_01_000000_do_stuff', Migrate::DOWN] + ); + $migration->expects($this->atLeastOnce()) + ->method('setMigrated') + ->withConsecutive( + ['9876_03_22_210000_random_hack', Migrate::UP], + ['9999_99_99_999999_another_foo', Migrate::UP], + ['9876_03_22_210000_random_hack', Migrate::UP], + ['4567_11_01_000000_do_stuff', Migrate::DOWN] + ); + + $messages = []; + $migration->setOutput(function ($text) use (&$messages) { + $messages[] = $text; + }); + + $migration->run('foo', Migrate::UP); + + $this->assertCount(4, $messages); + foreach ( + [ + 'init_foo' => 'skipping', + 'do_stuff' => 'skipping', + 'random_hack' => 'migrating', + 'another_foo' => 'migrating', + ] as $value => $type + ) { + $contains = false; + foreach ($messages as $message) { + if (!Str::contains(strtolower($message), $type) || !Str::contains(strtolower($message), $value)) { + continue; + } + + $contains = true; + break; + } + + $this->assertTrue($contains, sprintf('Missing message "%s: %s"', $type, $value)); + } + + $messages = []; + $migration->run('foo', Migrate::UP, true); + $this->assertCount(3, $messages); + + $migration->run('foo', Migrate::DOWN, true); + } + + /** + * @covers \Engelsystem\Database\Migration\Migrate::getMigrated + * @covers \Engelsystem\Database\Migration\Migrate::migrate + * @covers \Engelsystem\Database\Migration\Migrate::setMigrated + * @covers \Engelsystem\Database\Migration\Migrate::getMigrationFiles + * @covers \Engelsystem\Database\Migration\Migrate::initMigration + * @covers \Engelsystem\Database\Migration\Migrate::getTableQuery + */ + public function testRunIntegration() + { + $app = new Application(); + $dbManager = new CapsuleManager($app); + $dbManager->addConnection(['driver' => 'sqlite', 'database' => ':memory:']); + $dbManager->bootEloquent(); + $db = $dbManager->getConnection(); + $db->useDefaultSchemaGrammar(); + $scheme = $db->getSchemaBuilder(); + + $app->instance('scheme', $scheme); + $app->bind(SchemaBuilder::class, 'scheme'); + + $migration = new Migrate($scheme, $app); + + $messages = []; + $migration->setOutput(function ($msg) use (&$messages) { + $messages[] = $msg; + }); + + $migration->run(__DIR__ . '/Stub', Migrate::UP); + + $this->assertTrue($scheme->hasTable('migrations')); + + $migrations = $db->table('migrations')->get(); + $this->assertCount(3, $migrations); + + $this->assertTrue($migrations->contains('migration', '2001_04_11_123456_create_lorem_ipsum_table')); + $this->assertTrue($migrations->contains('migration', '2017_12_24_053300_another_stuff')); + $this->assertTrue($migrations->contains('migration', '2022_12_22_221222_add_some_feature')); + + $this->assertTrue($scheme->hasTable('lorem_ipsum')); + + $migration->run(__DIR__ . '/Stub', Migrate::DOWN, true); + + $migrations = $db->table('migrations')->get(); + $this->assertCount(2, $migrations); + + $migration->run(__DIR__ . '/Stub', Migrate::DOWN); + + $migrations = $db->table('migrations')->get(); + $this->assertCount(0, $migrations); + + $this->assertFalse($scheme->hasTable('lorem_ipsum')); + } +} diff --git a/tests/Unit/Database/Migration/MigrationServiceProviderTest.php b/tests/Unit/Database/Migration/MigrationServiceProviderTest.php new file mode 100644 index 00000000..a99cdebe --- /dev/null +++ b/tests/Unit/Database/Migration/MigrationServiceProviderTest.php @@ -0,0 +1,55 @@ +getMockBuilder(Migrate::class) + ->disableOriginalConstructor() + ->getMock(); + /** @var MockObject|CapsuleManager $dbManager */ + $dbManager = $this->getMockBuilder(CapsuleManager::class) + ->disableOriginalConstructor() + ->getMock(); + /** @var MockObject|Connection $dbConnection */ + $dbConnection = $this->getMockBuilder(Connection::class) + ->disableOriginalConstructor() + ->getMock(); + /** @var MockObject|SchemaBuilder $schemaBuilder */ + $schemaBuilder = $this->getMockBuilder(SchemaBuilder::class) + ->disableOriginalConstructor() + ->getMock(); + + $app = $this->getApp(['make', 'instance', 'bind']); + + $app->expects($this->atLeastOnce()) + ->method('instance') + ->withConsecutive(['db.scheme'], ['db.migration']) + ->willReturnOnConsecutiveCalls($schemaBuilder, $migration); + + $this->setExpects($app, 'bind', [SchemaBuilder::class, 'db.scheme']); + $this->setExpects($app, 'make', [Migrate::class], $migration); + + $this->setExpects($dbConnection, 'getSchemaBuilder', null, $schemaBuilder); + $this->setExpects($dbManager, 'getConnection', null, $dbConnection); + Db::setDbManager($dbManager); + + $serviceProvider = new MigrationServiceProvider($app); + $serviceProvider->register(); + } +} diff --git a/tests/Unit/Database/Migration/MigrationTest.php b/tests/Unit/Database/Migration/MigrationTest.php new file mode 100644 index 00000000..43bded09 --- /dev/null +++ b/tests/Unit/Database/Migration/MigrationTest.php @@ -0,0 +1,24 @@ +getMockBuilder(SchemaBuilder::class) + ->disableOriginalConstructor() + ->getMock(); + + $instance = new AnotherStuff($schemaBuilder); + $this->assertAttributeEquals($schemaBuilder, 'schema', $instance); + } +} diff --git a/tests/Unit/Database/Migration/Stub/2001_04_11_123456_create_lorem_ipsum_table.php b/tests/Unit/Database/Migration/Stub/2001_04_11_123456_create_lorem_ipsum_table.php new file mode 100644 index 00000000..0cc89e07 --- /dev/null +++ b/tests/Unit/Database/Migration/Stub/2001_04_11_123456_create_lorem_ipsum_table.php @@ -0,0 +1,27 @@ +schema->create('lorem_ipsum', function (Blueprint $table) { + $table->increments('id'); + $table->string('name')->unique(); + $table->string('email'); + }); + } + + /** + * Reverse the migration + */ + public function down() + { + $this->schema->dropIfExists('lorem_ipsum'); + } +} diff --git a/tests/Unit/Database/Migration/Stub/2017_12_24_053300_another_stuff.php b/tests/Unit/Database/Migration/Stub/2017_12_24_053300_another_stuff.php new file mode 100644 index 00000000..d4d7e5f8 --- /dev/null +++ b/tests/Unit/Database/Migration/Stub/2017_12_24_053300_another_stuff.php @@ -0,0 +1,22 @@ +