Skip to content

Commit

Permalink
Get Environment tests passing with migrations engine
Browse files Browse the repository at this point in the history
Using the PhinxAdapter we can maintain compatibility with existing
Migrations, and have an API solution for both now as we transition onto
the migrations engine and after phinx is removed, the API doesn't change
much just the namespaces change.
  • Loading branch information
markstory committed Jan 23, 2024
1 parent d294994 commit 67436e5
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 83 deletions.
52 changes: 31 additions & 21 deletions src/Migration/Environment.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

use Migrations\Db\Adapter\AdapterFactory;
use Migrations\Db\Adapter\AdapterInterface;
use Migrations\Db\Adapter\PhinxAdapter;
use PDO;
use Phinx\Migration\MigrationInterface;
use Phinx\Seed\SeedInterface;
Expand Down Expand Up @@ -78,10 +79,11 @@ public function executeMigration(MigrationInterface $migration, string $directio
$migration->setMigratingUp($direction === MigrationInterface::UP);

$startTime = time();
// Need to get a phinx interface adapter here. We will need to have a shim
// to bridge the interfaces. Changing the MigrationInterface is tricky
// because of the method names.
$migration->setAdapter($this->getAdapter());
// Use an adapter shim to bridge between the new migrations
// engine and the Phinx compatible interface
$adapter = $this->getAdapter();
$phinxShim = new PhinxAdapter($adapter);
$migration->setAdapter($phinxShim);

$migration->preFlightCheck();

Expand All @@ -90,24 +92,29 @@ public function executeMigration(MigrationInterface $migration, string $directio
}

// begin the transaction if the adapter supports it
if ($this->getAdapter()->hasTransactions()) {
$this->getAdapter()->beginTransaction();
if ($adapter->hasTransactions()) {
$adapter->beginTransaction();
}

if (!$fake) {
// Run the migration
if (method_exists($migration, MigrationInterface::CHANGE)) {
if ($direction === MigrationInterface::DOWN) {
// Create an instance of the ProxyAdapter so we can record all
// Create an instance of the RecordingAdapter so we can record all
// of the migration commands for reverse playback

/** @var \Phinx\Db\Adapter\ProxyAdapter $proxyAdapter */
$proxyAdapter = AdapterFactory::instance()
->getWrapper('proxy', $this->getAdapter());
$migration->setAdapter($proxyAdapter);
/** @var \Migrations\Db\Adapter\RecordingAdapter $recordAdapter */
$recordAdapter = AdapterFactory::instance()
->getWrapper('record', $adapter);

// Wrap the adapter with a phinx shim to maintain contain
$phinxAdapter = new PhinxAdapter($recordAdapter);
$migration->setAdapter($phinxAdapter);

$migration->{MigrationInterface::CHANGE}();
$proxyAdapter->executeInvertedCommands();
$migration->setAdapter($this->getAdapter());
$recordAdapter->executeInvertedCommands();

$migration->setAdapter(new PhinxAdapter($this->getAdapter()));
} else {
$migration->{MigrationInterface::CHANGE}();
}
Expand All @@ -117,11 +124,11 @@ public function executeMigration(MigrationInterface $migration, string $directio
}

// Record it in the database
$this->getAdapter()->migrated($migration, $direction, date('Y-m-d H:i:s', $startTime), date('Y-m-d H:i:s', time()));
$adapter->migrated($migration, $direction, date('Y-m-d H:i:s', $startTime), date('Y-m-d H:i:s', time()));

// commit the transaction if the adapter supports it
if ($this->getAdapter()->hasTransactions()) {
$this->getAdapter()->commitTransaction();
if ($adapter->hasTransactions()) {
$adapter->commitTransaction();
}

$migration->postFlightCheck();
Expand All @@ -135,14 +142,17 @@ public function executeMigration(MigrationInterface $migration, string $directio
*/
public function executeSeed(SeedInterface $seed): void
{
$seed->setAdapter($this->getAdapter());
$adapter = $this->getAdapter();
$phinxAdapter = new PhinxAdapter($adapter);

$seed->setAdapter($phinxAdapter);
if (method_exists($seed, SeedInterface::INIT)) {
$seed->{SeedInterface::INIT}();
}

// begin the transaction if the adapter supports it
if ($this->getAdapter()->hasTransactions()) {
$this->getAdapter()->beginTransaction();
if ($adapter->hasTransactions()) {
$adapter->beginTransaction();

Check warning on line 155 in src/Migration/Environment.php

View check run for this annotation

Codecov / codecov/patch

src/Migration/Environment.php#L155

Added line #L155 was not covered by tests
}

// Run the seeder
Expand All @@ -151,8 +161,8 @@ public function executeSeed(SeedInterface $seed): void
}

// commit the transaction if the adapter supports it
if ($this->getAdapter()->hasTransactions()) {
$this->getAdapter()->commitTransaction();
if ($adapter->hasTransactions()) {
$adapter->commitTransaction();

Check warning on line 165 in src/Migration/Environment.php

View check run for this annotation

Codecov / codecov/patch

src/Migration/Environment.php#L165

Added line #L165 was not covered by tests
}
}

Expand Down
86 changes: 24 additions & 62 deletions tests/TestCase/Migration/EnvironmentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@
namespace Test\Phinx\Migration;

use Migrations\Db\Adapter\AdapterFactory;

Check failure on line 6 in tests/TestCase/Migration/EnvironmentTest.php

View workflow job for this annotation

GitHub Actions / cs-stan / Coding Standard & Static Analysis

Type Migrations\Db\Adapter\AdapterFactory is not used in this file.
use Migrations\Db\Adapter\PdoAdapter;
use Migrations\Db\Adapter\PhinxAdapter;

Check failure on line 8 in tests/TestCase/Migration/EnvironmentTest.php

View workflow job for this annotation

GitHub Actions / cs-stan / Coding Standard & Static Analysis

Type Migrations\Db\Adapter\PhinxAdapter is not used in this file.
use Migrations\Migration\Environment;
use PDO;

Check failure on line 10 in tests/TestCase/Migration/EnvironmentTest.php

View workflow job for this annotation

GitHub Actions / cs-stan / Coding Standard & Static Analysis

Type PDO is not used in this file.
use Phinx\Migration\AbstractMigration;
use Phinx\Migration\MigrationInterface;
use Phinx\Seed\AbstractSeed;
use Phinx\Seed\SeedInterface;

Check failure on line 14 in tests/TestCase/Migration/EnvironmentTest.php

View workflow job for this annotation

GitHub Actions / cs-stan / Coding Standard & Static Analysis

Type Phinx\Seed\SeedInterface is not used in this file.
use PHPUnit\Framework\TestCase;
use RuntimeException;
use stdClass;
Expand Down Expand Up @@ -59,42 +64,6 @@ public function testNoAdapter()
$this->environment->getAdapter();
}

private function getPdoMock()
{
$pdoMock = $this->getMockBuilder(PDO::class)->disableOriginalConstructor()->getMock();
$attributes = [];
$pdoMock->method('setAttribute')->will($this->returnCallback(function ($attribute, $value) use (&$attributes) {
$attributes[$attribute] = $value;

return true;
}));
$pdoMock->method('getAttribute')->will($this->returnCallback(function ($attribute) use (&$attributes) {
return $attributes[$attribute] ?? 'pdomock';
}));

return $pdoMock;
}

public function testGetAdapterWithExistingPdoInstance()
{
$this->markTestIncomplete('Requires a shim adapter to pass.');
$adapter = $this->getMockForAbstractClass('\Migrations\Db\Adapter\PdoAdapter', [['foo' => 'bar']]);
AdapterFactory::instance()->registerAdapter('pdomock', $adapter);
$this->environment->setOptions(['connection' => $this->getPdoMock()]);
$options = $this->environment->getAdapter()->getOptions();
$this->assertEquals('pdomock', $options['adapter']);
}

public function testSetPdoAttributeToErrmodeException()
{
$this->markTestIncomplete('Requires a shim adapter to pass.');
$adapter = $this->getMockForAbstractClass('\Migrations\Db\Adapter\PdoAdapter', [['foo' => 'bar']]);
AdapterFactory::instance()->registerAdapter('pdomock', $adapter);
$this->environment->setOptions(['connection' => $this->getPdoMock()]);
$options = $this->environment->getAdapter()->getOptions();
$this->assertEquals(PDO::ERRMODE_EXCEPTION, $options['connection']->getAttribute(PDO::ATTR_ERRMODE));
}

public function testGetAdapterWithBadExistingPdoInstance()
{
$this->environment->setOptions(['connection' => new stdClass()]);
Expand All @@ -115,7 +84,7 @@ public function testSchemaName()

public function testCurrentVersion()
{
$stub = $this->getMockBuilder('\Migrations\Db\Adapter\PdoAdapter')
$stub = $this->getMockBuilder(PdoAdapter::class)
->setConstructorArgs([[]])
->getMock();
$stub->expects($this->any())
Expand All @@ -130,7 +99,7 @@ public function testCurrentVersion()
public function testExecutingAMigrationUp()
{
// stub adapter
$adapterStub = $this->getMockBuilder('\Migrations\Db\Adapter\PdoAdapter')
$adapterStub = $this->getMockBuilder(PdoAdapter::class)
->setConstructorArgs([[]])
->getMock();
$adapterStub->expects($this->once())
Expand All @@ -140,21 +109,20 @@ public function testExecutingAMigrationUp()
$this->environment->setAdapter($adapterStub);

// up
$upMigration = $this->getMockBuilder('\Phinx\Migration\AbstractMigration')
$upMigration = $this->getMockBuilder(AbstractMigration::class)
->setConstructorArgs(['mockenv', '20110301080000'])
->addMethods(['up'])
->getMock();
$upMigration->expects($this->once())
->method('up');

$this->markTestIncomplete('Requires a shim adapter to pass.');
$this->environment->executeMigration($upMigration, MigrationInterface::UP);
}

public function testExecutingAMigrationDown()
{
// stub adapter
$adapterStub = $this->getMockBuilder('\Migrations\Db\Adapter\PdoAdapter')
$adapterStub = $this->getMockBuilder(PdoAdapter::class)
->setConstructorArgs([[]])
->getMock();
$adapterStub->expects($this->once())
Expand All @@ -164,22 +132,20 @@ public function testExecutingAMigrationDown()
$this->environment->setAdapter($adapterStub);

// down
$downMigration = $this->getMockBuilder('\Phinx\Migration\AbstractMigration')
$downMigration = $this->getMockBuilder(AbstractMigration::class)
->setConstructorArgs(['mockenv', '20110301080000'])
->addMethods(['down'])
->getMock();
$downMigration->expects($this->once())
->method('down');

$this->markTestIncomplete('Requires a shim adapter to pass.');
$this->environment->executeMigration($downMigration, MigrationInterface::DOWN);
}

public function testExecutingAMigrationWithTransactions()
{
$this->markTestIncomplete('Requires a shim adapter to pass.');
// stub adapter
$adapterStub = $this->getMockBuilder('\Migrations\Db\Adapter\PdoAdapter')
$adapterStub = $this->getMockBuilder(PdoAdapter::class)
->setConstructorArgs([[]])
->getMock();
$adapterStub->expects($this->once())
Expand All @@ -195,7 +161,7 @@ public function testExecutingAMigrationWithTransactions()
$this->environment->setAdapter($adapterStub);

// migrate
$migration = $this->getMockBuilder('\Phinx\Migration\AbstractMigration')
$migration = $this->getMockBuilder(AbstractMigration::class)
->setConstructorArgs(['mockenv', '20110301080000'])
->addMethods(['up'])
->getMock();
Expand All @@ -207,9 +173,8 @@ public function testExecutingAMigrationWithTransactions()

public function testExecutingAChangeMigrationUp()
{
$this->markTestIncomplete('Requires a shim adapter to pass.');
// stub adapter
$adapterStub = $this->getMockBuilder('\Migrations\Db\Adapter\PdoAdapter')
$adapterStub = $this->getMockBuilder(PdoAdapter::class)
->setConstructorArgs([[]])
->getMock();
$adapterStub->expects($this->once())
Expand All @@ -219,7 +184,7 @@ public function testExecutingAChangeMigrationUp()
$this->environment->setAdapter($adapterStub);

// migration
$migration = $this->getMockBuilder('\Phinx\Migration\AbstractMigration')
$migration = $this->getMockBuilder(AbstractMigration::class)
->setConstructorArgs(['mockenv', '20130301080000'])
->addMethods(['change'])
->getMock();
Expand All @@ -231,9 +196,8 @@ public function testExecutingAChangeMigrationUp()

public function testExecutingAChangeMigrationDown()
{
$this->markTestIncomplete('Requires a shim adapter to pass.');
// stub adapter
$adapterStub = $this->getMockBuilder('\Migrations\Db\Adapter\PdoAdapter')
$adapterStub = $this->getMockBuilder(PdoAdapter::class)
->setConstructorArgs([[]])
->getMock();
$adapterStub->expects($this->once())
Expand All @@ -243,7 +207,7 @@ public function testExecutingAChangeMigrationDown()
$this->environment->setAdapter($adapterStub);

// migration
$migration = $this->getMockBuilder('\Phinx\Migration\AbstractMigration')
$migration = $this->getMockBuilder(AbstractMigration::class)
->setConstructorArgs(['mockenv', '20130301080000'])
->addMethods(['change'])
->getMock();
Expand All @@ -255,9 +219,8 @@ public function testExecutingAChangeMigrationDown()

public function testExecutingAFakeMigration()
{
$this->markTestIncomplete('Requires a shim adapter to pass.');
// stub adapter
$adapterStub = $this->getMockBuilder('\Migrations\Db\Adapter\PdoAdapter')
$adapterStub = $this->getMockBuilder(PdoAdapter::class)
->setConstructorArgs([[]])
->getMock();
$adapterStub->expects($this->once())
Expand All @@ -267,7 +230,7 @@ public function testExecutingAFakeMigration()
$this->environment->setAdapter($adapterStub);

// migration
$migration = $this->getMockBuilder('\Phinx\Migration\AbstractMigration')
$migration = $this->getMockBuilder(AbstractMigration::class)
->setConstructorArgs(['mockenv', '20130301080000'])
->addMethods(['change'])
->getMock();
Expand All @@ -288,9 +251,8 @@ public function testGettingInputObject()

public function testExecuteMigrationCallsInit()
{
$this->markTestIncomplete('Requires a shim adapter to pass.');
// stub adapter
$adapterStub = $this->getMockBuilder('\Migrations\Db\Adapter\PdoAdapter')
$adapterStub = $this->getMockBuilder(PdoAdapter::class)
->setConstructorArgs([[]])
->getMock();
$adapterStub->expects($this->once())
Expand All @@ -300,7 +262,7 @@ public function testExecuteMigrationCallsInit()
$this->environment->setAdapter($adapterStub);

// up
$upMigration = $this->getMockBuilder('\Phinx\Migration\AbstractMigration')
$upMigration = $this->getMockBuilder(AbstractMigration::class)
->setConstructorArgs(['mockenv', '20110301080000'])
->addMethods(['up', 'init'])
->getMock();
Expand All @@ -314,17 +276,17 @@ public function testExecuteMigrationCallsInit()

public function testExecuteSeedInit()
{
$this->markTestIncomplete('Requires a shim adapter to pass.');
// stub adapter
$adapterStub = $this->getMockBuilder('\Migrations\Db\Adapter\PdoAdapter')
$adapterStub = $this->getMockBuilder(PdoAdapter::class)
->setConstructorArgs([[]])
->getMock();

$this->environment->setAdapter($adapterStub);

// up
$seed = $this->getMockBuilder('\Migrations\AbstractSeed')
->onlyMethods(['run', 'init'])
$seed = $this->getMockBuilder(AbstractSeed::class)
->addMethods(['init'])
->onlyMethods(['run'])
->getMock();

$seed->expects($this->once())
Expand Down

0 comments on commit 67436e5

Please sign in to comment.