diff --git a/.github/workflows/code-checks.yml b/.github/workflows/code-checks.yml index 00c40ed..eb1a46c 100644 --- a/.github/workflows/code-checks.yml +++ b/.github/workflows/code-checks.yml @@ -12,8 +12,6 @@ jobs: strategy: matrix: php: - - '7.4' - - '8.0' - '8.1' - '8.2' - '8.3' diff --git a/.gitignore b/.gitignore index 4901aab..a3ee6db 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ -/vendor +/.phpunit.cache/ +/vendor/ /composer.lock -/.phpunit.result.cache diff --git a/.runConfigurations/All tests.run.xml b/.runConfigurations/All tests.run.xml index 10b55ec..147bdd0 100644 --- a/.runConfigurations/All tests.run.xml +++ b/.runConfigurations/All tests.run.xml @@ -8,7 +8,7 @@ - + \ No newline at end of file diff --git a/.runConfigurations/All unit tests.run.xml b/.runConfigurations/All unit tests.run.xml index a42ab5a..5d27a5b 100644 --- a/.runConfigurations/All unit tests.run.xml +++ b/.runConfigurations/All unit tests.run.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.runConfigurations/Integration tests.run.xml b/.runConfigurations/Integration tests.run.xml index 6c8e2fb..0bb6431 100644 --- a/.runConfigurations/Integration tests.run.xml +++ b/.runConfigurations/Integration tests.run.xml @@ -8,7 +8,7 @@ - + \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 32f97a7..de7d454 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Removed +- **BC break**: Removed support for PHP versions <= v8.0 as they are no longer + [actively supported](https://php.net/supported-versions.php) by the PHP project. ## [2.0.2] - 2025-02-08 ### Changed diff --git a/composer.json b/composer.json index 4206539..c9adfdc 100644 --- a/composer.json +++ b/composer.json @@ -19,10 +19,10 @@ } ], "require": { - "php": "^7.4 || ^8.0", + "php": "^8.1", "ext-pdo": "*", "ext-pdo_mysql": "*", - "symfony/console": "^3.2|^4|^5 || ^6 || ^7" + "symfony/console": "^6 || ^7" }, "autoload": { "psr-4": { @@ -30,7 +30,7 @@ } }, "require-dev": { - "phpunit/phpunit": "^9", + "phpunit/phpunit": "^10", "symplify/easy-coding-standard": "^12" }, "autoload-dev": { diff --git a/ecs.php b/ecs.php index 1650e9d..3578426 100644 --- a/ecs.php +++ b/ecs.php @@ -49,4 +49,19 @@ [ 'closure_fn_spacing' => 'none', ], + ) + + /* + * Rule from PER Coding Style 2.6: + * "If the list is split across multiple lines, then the last item MUST have a trailing comma." + */ + ->withConfiguredRule( + \PhpCsFixer\Fixer\ControlStructure\TrailingCommaInMultilineFixer::class, + [ + 'elements' => [ + \PhpCsFixer\Fixer\ControlStructure\TrailingCommaInMultilineFixer::ELEMENTS_ARGUMENTS, + \PhpCsFixer\Fixer\ControlStructure\TrailingCommaInMultilineFixer::ELEMENTS_ARRAYS, + \PhpCsFixer\Fixer\ControlStructure\TrailingCommaInMultilineFixer::ELEMENTS_PARAMETERS, + ], + ], ); diff --git a/phpunit.xml.dist b/phpunit.xml.dist index f8a8cd9..70113d3 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,10 +1,10 @@ @@ -21,9 +21,9 @@ tests - + src - + diff --git a/src/SchemaDiff.php b/src/SchemaDiff.php index 9bd423e..34c1c89 100644 --- a/src/SchemaDiff.php +++ b/src/SchemaDiff.php @@ -12,12 +12,9 @@ */ class SchemaDiff { - private OutputInterface $output; - - public function __construct(OutputInterface $output) - { - $this->output = $output; - + public function __construct( + private readonly OutputInterface $output, + ) { $this->initStyles(); } @@ -51,8 +48,8 @@ public function diff(SchemaInfo $schema1, SchemaInfo $schema2): bool $tables = array_unique( array_merge( $schema1->getTables(), - $schema2->getTables() - ) + $schema2->getTables(), + ), ); $msg = 'Missing table %s
missing on %s exists on %s'; @@ -63,7 +60,7 @@ public function diff(SchemaInfo $schema1, SchemaInfo $schema2): bool $msg, $tableName, $schema1->getName() . '@1', - $schema2->getName() . '@2' + $schema2->getName() . '@2', )); continue; @@ -74,7 +71,7 @@ public function diff(SchemaInfo $schema1, SchemaInfo $schema2): bool $msg, $tableName, $schema2->getName() . '@2', - $schema1->getName() . '@1' + $schema1->getName() . '@1', )); continue; @@ -150,8 +147,8 @@ private function compareColumns(SchemaInfo $schema1, SchemaInfo $schema2, string $tableName, $columnName, $schema1->getName() . '@1', - $schema2->getName() . '@2' - ) + $schema2->getName() . '@2', + ), ); continue; @@ -165,8 +162,8 @@ private function compareColumns(SchemaInfo $schema1, SchemaInfo $schema2, string $tableName, $columnName, $schema2->getName() . '@2', - $schema1->getName() . '@1' - ) + $schema1->getName() . '@1', + ), ); continue; @@ -216,7 +213,7 @@ private function compareIndexes(SchemaInfo $schema1, SchemaInfo $schema2, string $tableName, $indexName, $schema1->getName() . '@1', - $schema2->getName() . '@2' + $schema2->getName() . '@2', )); continue; @@ -229,7 +226,7 @@ private function compareIndexes(SchemaInfo $schema1, SchemaInfo $schema2, string $tableName, $indexName, $schema2->getName() . '@2', - $schema1->getName() . '@1' + $schema1->getName() . '@1', )); continue; diff --git a/src/SchemaDiffCommand.php b/src/SchemaDiffCommand.php index 5d1b6fa..d4183e5 100644 --- a/src/SchemaDiffCommand.php +++ b/src/SchemaDiffCommand.php @@ -16,10 +16,6 @@ */ class SchemaDiffCommand extends Command { - private SchemaInfoFactory $schemaInfoFactory; - - private \Closure $schemaDiffFactory; - private array $ignoreDatabases; private ?string $ignoreDatabasesRegex; @@ -37,12 +33,9 @@ class SchemaDiffCommand extends Command private ?string $tablesRegex; public function __construct( - SchemaInfoFactory $schemaInfoFactory, - \Closure $schemaDiffFactory + private readonly SchemaInfoFactory $schemaInfoFactory, + private readonly \Closure $schemaDiffFactory, ) { - $this->schemaInfoFactory = $schemaInfoFactory; - $this->schemaDiffFactory = $schemaDiffFactory; - parent::__construct(); } @@ -65,69 +58,69 @@ protected function configure(): void $this->addArgument( 'dsn1', InputArgument::REQUIRED, - 'DSN to first schema, needs to contain the main database' + 'DSN to first schema, needs to contain the main database', ); $this->addArgument( 'dsn2', InputArgument::REQUIRED, - 'DSN to second schema, if it contains a database that will be used, otherwise uses the filter options' + 'DSN to second schema, if it contains a database that will be used, otherwise uses the filter options', ); $this->addOption( 'ignore-databases', null, InputOption::VALUE_REQUIRED, - 'Ignore this comma-separated list of databases' + 'Ignore this comma-separated list of databases', ); $this->addOption( 'ignore-databases-regex', null, InputOption::VALUE_REQUIRED, - 'Ignore databases whose names match this regex' + 'Ignore databases whose names match this regex', ); $this->addOption( 'databases', null, InputOption::VALUE_REQUIRED, - 'Only compare this comma-separated list of databases' + 'Only compare this comma-separated list of databases', ); $this->addOption( 'databases-regex', null, InputOption::VALUE_REQUIRED, - 'Only compare databases whose names match this regex' + 'Only compare databases whose names match this regex', ); $this->addOption( 'ignore-tables', null, InputOption::VALUE_REQUIRED, - 'Ignore this comma-separated list of tables. Table names may be qualified with the database name' + 'Ignore this comma-separated list of tables. Table names may be qualified with the database name', ); $this->addOption( 'ignore-tables-regex', null, InputOption::VALUE_REQUIRED, - 'Ignore tables whose names match the regex' + 'Ignore tables whose names match the regex', ); $this->addOption( 'tables', null, InputOption::VALUE_REQUIRED, - 'Compare only this comma-separated list of tables. Table names may be qualified with the database name' + 'Compare only this comma-separated list of tables. Table names may be qualified with the database name', ); $this->addOption( 'tables-regex', null, InputOption::VALUE_REQUIRED, - 'Compare only tables whose names match this regex' + 'Compare only tables whose names match this regex', ); } @@ -177,7 +170,7 @@ private function createSchemaInfo(\PDO $pdo, string $database, OutputInterface $ $database, function ($tableName) use ($database, $output): bool { return $this->isTableAllowed($database, $tableName, $output); - } + }, ); } diff --git a/src/SchemaInfo.php b/src/SchemaInfo.php index 66d71f8..10e9cdd 100644 --- a/src/SchemaInfo.php +++ b/src/SchemaInfo.php @@ -9,17 +9,11 @@ */ class SchemaInfo { - private string $name; - - private array $schemaData; - - private array $tableData; - - public function __construct(string $name, array $schemaData, array $tableData) - { - $this->name = $name; - $this->schemaData = $schemaData; - $this->tableData = $tableData; + public function __construct( + private readonly string $name, + private readonly array $schemaData, + private readonly array $tableData, + ) { } public function getName(): string diff --git a/tests/Integration/IntegrationTestCase.php b/tests/Integration/IntegrationTestCase.php index e62dbcf..84ad700 100644 --- a/tests/Integration/IntegrationTestCase.php +++ b/tests/Integration/IntegrationTestCase.php @@ -32,7 +32,7 @@ protected function setUp(): void \PDO::ATTR_TIMEOUT => 2, \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION, \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC, - ] + ], ); } @@ -56,7 +56,7 @@ final protected function createTestTable( bool $charCol = true, bool $charIdx = false, string $colCharset = null, - string $tableCharset = 'ascii' + string $tableCharset = 'ascii', ) { $schemaTableQuoted = '`' . $schemaName . "`.`{$tableName}`"; diff --git a/tests/Integration/SchemaDiffCommandTest.php b/tests/Integration/SchemaDiffCommandTest.php index 6a1609d..3a460e9 100644 --- a/tests/Integration/SchemaDiffCommandTest.php +++ b/tests/Integration/SchemaDiffCommandTest.php @@ -7,16 +7,17 @@ use Phlib\SchemaDiff\SchemaDiff; use Phlib\SchemaDiff\SchemaDiffCommand; use Phlib\SchemaDiff\SchemaInfoFactory; +use PHPUnit\Framework\Attributes\Group; use Symfony\Component\Console\Application; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Tester\CommandTester; /** * @package phlib/schemadiff - * @group integration * * This only runs basic table-centric tests that are handled by `SchemaDiff` as it's relying on a limited test database. */ +#[Group('integration')] class SchemaDiffCommandTest extends SchemaDiffTestCase { private SchemaDiffCommand $command; diff --git a/tests/Integration/SchemaDiffTest.php b/tests/Integration/SchemaDiffTest.php index 021479c..1319ac6 100644 --- a/tests/Integration/SchemaDiffTest.php +++ b/tests/Integration/SchemaDiffTest.php @@ -6,12 +6,13 @@ use Phlib\SchemaDiff\SchemaDiff; use Phlib\SchemaDiff\SchemaInfoFactory; +use PHPUnit\Framework\Attributes\Group; use Symfony\Component\Console\Output\BufferedOutput; /** * @package phlib/schemadiff - * @group integration */ +#[Group('integration')] class SchemaDiffTest extends SchemaDiffTestCase { protected function runDiff(string $tableName, string &$output = null): bool diff --git a/tests/Integration/SchemaDiffTestCase.php b/tests/Integration/SchemaDiffTestCase.php index b844819..9ec85c2 100644 --- a/tests/Integration/SchemaDiffTestCase.php +++ b/tests/Integration/SchemaDiffTestCase.php @@ -4,6 +4,8 @@ namespace Phlib\SchemaDiff\Test\Integration; +use PHPUnit\Framework\Attributes\DataProvider; + /** * @package phlib/schemadiff */ @@ -25,7 +27,7 @@ public function testSame(): void static::assertEmpty($output); } - public function dataSchemaOrder(): array + public static function dataSchemaOrder(): array { return [ 'one-two' => [1, 2], @@ -33,9 +35,7 @@ public function dataSchemaOrder(): array ]; } - /** - * @dataProvider dataSchemaOrder - */ + #[DataProvider('dataSchemaOrder')] public function testMissingTable(int $first, int $second): void { $tableName = $this->generateTableName(); @@ -51,9 +51,7 @@ public function testMissingTable(int $first, int $second): void static::assertStringStartsWith($expected, $output); } - /** - * @dataProvider dataSchemaOrder - */ + #[DataProvider('dataSchemaOrder')] public function testMissingColumn(int $first, int $second): void { $tableName = $this->generateTableName(); @@ -70,9 +68,7 @@ public function testMissingColumn(int $first, int $second): void static::assertStringContainsString($expected, $output); } - /** - * @dataProvider dataSchemaOrder - */ + #[DataProvider('dataSchemaOrder')] public function testMissingIndex(int $first, int $second): void { $tableName = $this->generateTableName(); @@ -89,9 +85,7 @@ public function testMissingIndex(int $first, int $second): void static::assertStringStartsWith($expected, $output); } - /** - * @dataProvider dataSchemaOrder - */ + #[DataProvider('dataSchemaOrder')] public function testDiffColumnCharset(int $first, int $second): void { $tableName = $this->generateTableName(); @@ -110,9 +104,7 @@ public function testDiffColumnCharset(int $first, int $second): void static::assertStringContainsString(getenv('DB_DATABASE_' . $second) . "@{$second}=utf8mb4", $output); } - /** - * @dataProvider dataSchemaOrder - */ + #[DataProvider('dataSchemaOrder')] public function testDiffTableCharset(int $first, int $second): void { $tableName = $this->generateTableName(); diff --git a/tests/SchemaDiffCommandTest.php b/tests/SchemaDiffCommandTest.php index 37fb4c5..7bac439 100644 --- a/tests/SchemaDiffCommandTest.php +++ b/tests/SchemaDiffCommandTest.php @@ -8,6 +8,7 @@ use Phlib\SchemaDiff\SchemaDiffCommand; use Phlib\SchemaDiff\SchemaInfo; use Phlib\SchemaDiff\SchemaInfoFactory; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Application; @@ -53,9 +54,7 @@ function (): SchemaDiff { parent::setUp(); } - /** - * @dataProvider dataDsnInvalid - */ + #[DataProvider('dataDsnInvalid')] public function testDsnInvalid(string $dsn1, string $dsn2): void { $this->expectException(\InvalidArgumentException::class); @@ -67,9 +66,9 @@ public function testDsnInvalid(string $dsn1, string $dsn2): void ]); } - public function dataDsnInvalid(): iterable + public static function dataDsnInvalid(): iterable { - $validDsn = $this->createDsn(true); + $validDsn = static::createDsn(true); $invalidDsn = $validDsn['string'] . ',' . sha1(uniqid()) . '=' . sha1(uniqid()); @@ -84,15 +83,15 @@ public function testDsn1MissingDatabase(): void $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('DSN 1 missing database (D)'); - $dsn1 = $this->createDsn(false); - $dsn2 = $this->createDsn(true); + $dsn1 = static::createDsn(false); + $dsn2 = static::createDsn(true); $this->schemaInfoFactory->expects(static::exactly(2)) ->method('createPdo') - ->withConsecutive( - [$dsn1['parts']], - [$dsn2['parts']], - ); + ->willReturnMap([ + [$dsn1['parts'], $this->createStub(\PDO::class)], + [$dsn2['parts'], $this->createStub(\PDO::class)], + ]); $this->commandTester->execute([ 'dsn1' => $dsn1['string'], @@ -105,19 +104,15 @@ public function testTwoDbNoDiff(): void $pdo1 = $this->createMock(\PDO::class); $pdo2 = $this->createMock(\PDO::class); - $dsn1 = $this->createDsn(true); - $dsn2 = $this->createDsn(true); + $dsn1 = static::createDsn(true); + $dsn2 = static::createDsn(true); $this->schemaInfoFactory->expects(static::exactly(2)) ->method('createPdo') - ->withConsecutive( - [$dsn1['parts']], - [$dsn2['parts']], - ) - ->willReturnOnConsecutiveCalls( - $pdo1, - $pdo2, - ); + ->willReturnMap([ + [$dsn1['parts'], $pdo1], + [$dsn2['parts'], $pdo2], + ]); $schemaInfo1 = $this->createMock(SchemaInfo::class); $schemaInfo2 = $this->createMock(SchemaInfo::class); @@ -130,7 +125,7 @@ public function testTwoDbNoDiff(): void [ $schemaInfo1, $schemaInfo2, - ] + ], ); $this->schemaDiff->expects(static::once()) @@ -151,7 +146,7 @@ public function testTwoDbNoDiff(): void $output = $this->commandTester->getDisplay(); static::assertSame( implode("\n", $expectedOutput) . "\n", - $output + $output, ); } @@ -160,19 +155,15 @@ public function testMultipleDbNoDiff(): void $pdo1 = $this->createMock(\PDO::class); $pdo2 = $this->createMock(\PDO::class); - $dsn1 = $this->createDsn(true); - $dsn2 = $this->createDsn(false); + $dsn1 = static::createDsn(true); + $dsn2 = static::createDsn(false); $this->schemaInfoFactory->expects(static::exactly(2)) ->method('createPdo') - ->withConsecutive( - [$dsn1['parts']], - [$dsn2['parts']], - ) - ->willReturnOnConsecutiveCalls( - $pdo1, - $pdo2, - ); + ->willReturnMap([ + [$dsn1['parts'], $pdo1], + [$dsn2['parts'], $pdo2], + ]); $databases = [ sha1(uniqid('one')), @@ -203,16 +194,15 @@ public function testMultipleDbNoDiff(): void $schemaInfo1, $schemaInfo2, $schemaInfo3, - ] + ], ); $this->schemaDiff->expects(static::exactly(2)) ->method('diff') - ->withConsecutive( - [$schemaInfo1, $schemaInfo2], - [$schemaInfo1, $schemaInfo3], - ) - ->willReturn(false); + ->willReturnMap([ + [$schemaInfo1, $schemaInfo2, false], + [$schemaInfo1, $schemaInfo3, false], + ]); $this->commandTester->execute([ 'dsn1' => $dsn1['string'], @@ -227,31 +217,25 @@ public function testMultipleDbNoDiff(): void $output = $this->commandTester->getDisplay(); static::assertSame( implode("\n", $expectedOutput) . "\n", - $output + $output, ); } - /** - * @dataProvider dataMultipleDbIgnoreSystem - */ + #[DataProvider('dataMultipleDbIgnoreSystem')] public function testMultipleDbIgnoreSystem(string $systemDatabase): void { $pdo1 = $this->createMock(\PDO::class); $pdo2 = $this->createMock(\PDO::class); - $dsn1 = $this->createDsn(true); - $dsn2 = $this->createDsn(false); + $dsn1 = static::createDsn(true); + $dsn2 = static::createDsn(false); $this->schemaInfoFactory->expects(static::exactly(2)) ->method('createPdo') - ->withConsecutive( - [$dsn1['parts']], - [$dsn2['parts']], - ) - ->willReturnOnConsecutiveCalls( - $pdo1, - $pdo2, - ); + ->willReturnMap([ + [$dsn1['parts'], $pdo1], + [$dsn2['parts'], $pdo2], + ]); $databases = [ sha1(uniqid('one')), @@ -286,7 +270,7 @@ public function testMultipleDbIgnoreSystem(string $systemDatabase): void $schemaInfo1, $schemaInfo2, $schemaInfo3, - ] + ], ); // Add message for skipped database @@ -294,11 +278,10 @@ public function testMultipleDbIgnoreSystem(string $systemDatabase): void $this->schemaDiff->expects(static::exactly(2)) ->method('diff') - ->withConsecutive( - [$schemaInfo1, $schemaInfo2], - [$schemaInfo1, $schemaInfo3], - ) - ->willReturn(false); + ->willReturnMap([ + [$schemaInfo1, $schemaInfo2, false], + [$schemaInfo1, $schemaInfo3, false], + ]); $this->commandTester->execute([ 'dsn1' => $dsn1['string'], @@ -313,11 +296,11 @@ public function testMultipleDbIgnoreSystem(string $systemDatabase): void $output = $this->commandTester->getDisplay(); static::assertSame( implode("\n", $expectedOutput) . "\n", - $output + $output, ); } - public function dataMultipleDbIgnoreSystem(): array + public static function dataMultipleDbIgnoreSystem(): array { return [ 'mysql' => ['mysql'], @@ -330,7 +313,7 @@ public function dataMultipleDbIgnoreSystem(): array ]; } - public function dataAllowIgnoreRegex(): array + public static function dataAllowIgnoreRegex(): array { return [ 'ignore-plain' => ['ignore-plain'], @@ -340,16 +323,14 @@ public function dataAllowIgnoreRegex(): array ]; } - /** - * @dataProvider dataAllowIgnoreRegex - */ + #[DataProvider('dataAllowIgnoreRegex')] public function testMultipleDbIgnoreDatabases(string $allowIgnoreRegex): void { $pdo1 = $this->createMock(\PDO::class); $pdo2 = $this->createMock(\PDO::class); - $dsn1 = $this->createDsn(true); - $dsn2 = $this->createDsn(false); + $dsn1 = static::createDsn(true); + $dsn2 = static::createDsn(false); $ignore1 = 'ignore-' . sha1(uniqid('one')); $ignore2 = 'ignore-' . sha1(uniqid('two')); @@ -358,14 +339,10 @@ public function testMultipleDbIgnoreDatabases(string $allowIgnoreRegex): void $this->schemaInfoFactory->expects(static::exactly(2)) ->method('createPdo') - ->withConsecutive( - [$dsn1['parts']], - [$dsn2['parts']], - ) - ->willReturnOnConsecutiveCalls( - $pdo1, - $pdo2, - ); + ->willReturnMap([ + [$dsn1['parts'], $pdo1], + [$dsn2['parts'], $pdo2], + ]); $databases = [ $ignore1, @@ -401,7 +378,7 @@ public function testMultipleDbIgnoreDatabases(string $allowIgnoreRegex): void $schemaInfo1, $schemaInfo2, $schemaInfo3, - ] + ], ); // Add message for ignored databases @@ -424,11 +401,10 @@ public function testMultipleDbIgnoreDatabases(string $allowIgnoreRegex): void $this->schemaDiff->expects(static::exactly(2)) ->method('diff') - ->withConsecutive( - [$schemaInfo1, $schemaInfo2], - [$schemaInfo1, $schemaInfo3], - ) - ->willReturn(false); + ->willReturnMap([ + [$schemaInfo1, $schemaInfo2, false], + [$schemaInfo1, $schemaInfo3, false], + ]); $input = [ 'dsn1' => $dsn1['string'], @@ -458,20 +434,18 @@ public function testMultipleDbIgnoreDatabases(string $allowIgnoreRegex): void $output = $this->commandTester->getDisplay(); static::assertSame( implode("\n", $expectedOutput) . "\n", - $output + $output, ); } - /** - * @dataProvider dataAllowIgnoreRegex - */ + #[DataProvider('dataAllowIgnoreRegex')] public function testTwoDbIgnoreTables(string $allowIgnoreRegex): void { $pdo1 = $this->createMock(\PDO::class); $pdo2 = $this->createMock(\PDO::class); - $dsn1 = $this->createDsn(true); - $dsn2 = $this->createDsn(true); + $dsn1 = static::createDsn(true); + $dsn2 = static::createDsn(true); $ignore1 = 'ignore-' . sha1(uniqid('one')); $ignore2 = 'ignore-' . sha1(uniqid('two')); @@ -480,14 +454,10 @@ public function testTwoDbIgnoreTables(string $allowIgnoreRegex): void $this->schemaInfoFactory->expects(static::exactly(2)) ->method('createPdo') - ->withConsecutive( - [$dsn1['parts']], - [$dsn2['parts']], - ) - ->willReturnOnConsecutiveCalls( - $pdo1, - $pdo2, - ); + ->willReturnMap([ + [$dsn1['parts'], $pdo1], + [$dsn2['parts'], $pdo2], + ]); $schemaInfo1 = $this->createMock(SchemaInfo::class); $schemaInfo2 = $this->createMock(SchemaInfo::class); @@ -508,7 +478,7 @@ public function testTwoDbIgnoreTables(string $allowIgnoreRegex): void $schemaInfo1, $schemaInfo2, ], - $tables + $tables, ); // Add message for ignored databases @@ -533,9 +503,7 @@ public function testTwoDbIgnoreTables(string $allowIgnoreRegex): void $this->schemaDiff->expects(static::once()) ->method('diff') - ->withConsecutive( - [$schemaInfo1, $schemaInfo2], - ) + ->with($schemaInfo1, $schemaInfo2) ->willReturn(false); $input = [ @@ -566,15 +534,15 @@ public function testTwoDbIgnoreTables(string $allowIgnoreRegex): void $output = $this->commandTester->getDisplay(); static::assertSame( implode("\n", $expectedOutput) . "\n", - $output + $output, ); } - private function createDsn(bool $withDatabase = false): array + private static function createDsn(bool $withDatabase = false): array { $dsnParts = [ 'h' => sha1(uniqid('host')), - 'P' => rand(3000, 9000), + 'P' => (string)rand(3000, 9000), 'u' => sha1(uniqid('username')), 'p' => sha1(uniqid('password')), ]; @@ -600,11 +568,11 @@ private function setupFromPdoExpectation( string $database1, array $databases, array $schemaInfos, - array $tables = null + array $tables = null, ): array { $tableFilterConstraint = static::isInstanceOf(\Closure::class); if (is_array($tables)) { - $tableFilterConstraint = static::callback(function (\Closure $tableFilter) use ($tables) { + $tableFilterConstraint = static::callback(function (\Closure $tableFilter) use ($tables): bool { foreach ($tables as $tableName) { $tableFilter($tableName); } @@ -624,10 +592,30 @@ private function setupFromPdoExpectation( $output[] = "Fetching schema details for database {$database2}"; } - $this->schemaInfoFactory->expects(static::exactly(count($schemaInfos))) + $matcher = static::exactly(count($schemaInfos)); + $this->schemaInfoFactory->expects($matcher) ->method('fromPdo') - ->withConsecutive(...$arguments) - ->willReturnOnConsecutiveCalls(...$schemaInfos); + ->willReturnCallback(function ( + \PDO $actualConnection, + string $actualSchemaName, + callable $actualTableFilter = null, + ) use ( + $matcher, + $arguments, + $schemaInfos + ): SchemaInfo { + [ + $expectedPdo, + $expectedDatabase, + $tableFilterConstraint, + ] = $arguments[$matcher->numberOfInvocations() - 1]; + + static::assertSame($expectedPdo, $actualConnection); + static::assertSame($expectedDatabase, $actualSchemaName); + static::assertThat($actualTableFilter, $tableFilterConstraint); + + return $schemaInfos[$matcher->numberOfInvocations() - 1]; + }); return $output; } diff --git a/tests/SchemaDiffTest.php b/tests/SchemaDiffTest.php index 37a7f0e..0d414de 100644 --- a/tests/SchemaDiffTest.php +++ b/tests/SchemaDiffTest.php @@ -6,10 +6,12 @@ use Phlib\SchemaDiff\SchemaDiff; use Phlib\SchemaDiff\SchemaInfo; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Formatter\OutputFormatterStyle; +use Symfony\Component\Console\Formatter\OutputFormatterStyleInterface as StyleInterface; use Symfony\Component\Console\Output\OutputInterface; /** @@ -38,29 +40,20 @@ class SchemaDiffTest extends TestCase private string $schema2Name; - /** - * @dataProvider dataFormatterAddStyles - */ + #[DataProvider('dataFormatterAddStyles')] public function testFormatterAddStyles(array $hasStyles): void { $formatter = $this->createMock(OutputFormatter::class); $formatter->expects(static::exactly(5)) ->method('hasStyle') - ->withConsecutive( - ['schema'], - ['table'], - ['column'], - ['index'], - ['attribute'] - ) - ->willReturnOnConsecutiveCalls( - (bool)$hasStyles[0], - (bool)$hasStyles[1], - (bool)$hasStyles[2], - (bool)$hasStyles[3], - (bool)$hasStyles[4] - ); + ->willReturnMap([ + ['schema', (bool)$hasStyles[0]], + ['table', (bool)$hasStyles[1]], + ['column', (bool)$hasStyles[2]], + ['index', (bool)$hasStyles[3]], + ['attribute', (bool)$hasStyles[4]], + ]); $newStyles = [ ['schema', new OutputFormatterStyle('green')], @@ -70,13 +63,27 @@ public function testFormatterAddStyles(array $hasStyles): void ['attribute', new OutputFormatterStyle('yellow')], ]; - $expectedStyles = array_filter($newStyles, function ($idx) use ($hasStyles): bool { - return !$hasStyles[$idx]; - }, ARRAY_FILTER_USE_KEY); + $expectedStyles = array_values(array_filter( + $newStyles, + fn(int $idx): bool => !$hasStyles[$idx], + ARRAY_FILTER_USE_KEY, + )); - $formatter->expects(static::exactly(count($expectedStyles))) + $matcher = static::exactly(count($expectedStyles)); + $formatter->expects($matcher) ->method('setStyle') - ->withConsecutive(...$expectedStyles); + ->with( + static::callback(function (string $actualName) use ($matcher, $expectedStyles): bool { + $expected = $expectedStyles[$matcher->numberOfInvocations() - 1]; + static::assertSame($expected[0], $actualName); + return true; + }), + static::callback(function (StyleInterface $actualStyle) use ($matcher, $expectedStyles): bool { + $expected = $expectedStyles[$matcher->numberOfInvocations() - 1]; + static::assertEquals($expected[1], $actualStyle); + return true; + }), + ); $output = $this->createMock(OutputInterface::class); $output->expects(static::once()) @@ -86,7 +93,7 @@ public function testFormatterAddStyles(array $hasStyles): void new SchemaDiff($output); } - public function dataFormatterAddStyles(): array + public static function dataFormatterAddStyles(): array { $styleCount = 5; $totalCombos = 2 ** $styleCount; @@ -132,9 +139,7 @@ public function testDiffCompareSchemaInfo(): void static::assertTrue($hasDiff); } - /** - * @dataProvider dataSchemaOrder - */ + #[DataProvider('dataSchemaOrder')] public function testDiffHasTable(int $order1, int $order2): void { $this->initDiff(); @@ -215,9 +220,7 @@ public function testDiffCompareTableInfo(): void static::assertTrue($hasDiff); } - /** - * @dataProvider dataSchemaOrder - */ + #[DataProvider('dataSchemaOrder')] public function testDiffCompareColumns(int $order1, int $order2): void { $this->initDiff(); @@ -305,9 +308,7 @@ public function testDiffCompareColumnInfo(): void static::assertTrue($hasDiff); } - /** - * @dataProvider dataSchemaOrder - */ + #[DataProvider('dataSchemaOrder')] public function testDiffCompareIndexes(int $order1, int $order2): void { $this->initDiff(); @@ -497,7 +498,7 @@ private function initSchemaIndex(string $tableName): string return $indexName; } - public function dataSchemaOrder(): array + public static function dataSchemaOrder(): array { return [ 'one-two' => [1, 2], diff --git a/tests/SchemaInfoFactoryTest.php b/tests/SchemaInfoFactoryTest.php index 0fc4d83..601d493 100644 --- a/tests/SchemaInfoFactoryTest.php +++ b/tests/SchemaInfoFactoryTest.php @@ -179,29 +179,14 @@ public function testFromPdoSchemaInfo(): void ->with(\PDO::FETCH_GROUP | \PDO::FETCH_ASSOC) ->willReturn($indexData); - $statementMap = [ - [ - 'with' => [$this->schemaSql], - 'return' => $this->schemaStmt, - ], - [ - 'with' => [$this->tablesSql], - 'return' => $tablesStmt, - ], - [ - 'with' => [$this->columnsSql], - 'return' => $columnsStmt, - ], - [ - 'with' => [$this->indexSql], - 'return' => $indexStmt, - ], - ]; - - $this->pdo->expects(static::exactly(count($statementMap))) + $this->pdo->expects(static::exactly(4)) ->method('prepare') - ->withConsecutive(...array_column($statementMap, 'with')) - ->willReturnOnConsecutiveCalls(...array_column($statementMap, 'return')); + ->willReturnMap([ + [$this->schemaSql, [], $this->schemaStmt], + [$this->tablesSql, [], $tablesStmt], + [$this->columnsSql, [], $columnsStmt], + [$this->indexSql, [], $indexStmt], + ]); // Use the Factory to create the SchemaInfo $schemaInfo = (new SchemaInfoFactory())->fromPdo($this->pdo, $this->schemaName); @@ -216,15 +201,15 @@ public function testFromPdoSchemaInfo(): void // - tableData static::assertSame( $this->tableData[$this->tableName]['TABLE_INFO'], - $schemaInfo->getTableInfo($this->tableName) + $schemaInfo->getTableInfo($this->tableName), ); static::assertSame( $this->tableData[$this->tableName]['INDEXES']['PRIMARY'], - $schemaInfo->getIndexInfo($this->tableName, 'PRIMARY') + $schemaInfo->getIndexInfo($this->tableName, 'PRIMARY'), ); static::assertSame( $this->tableData[$this->tableName]['COLUMNS']['test_id'], - $schemaInfo->getColumnInfo($this->tableName, 'test_id') + $schemaInfo->getColumnInfo($this->tableName, 'test_id'), ); } @@ -265,29 +250,14 @@ public function testFromPdoTableFilter(): void ->with(\PDO::FETCH_ASSOC) ->willReturn($tablesData); - $statementMap = [ - [ - 'with' => [$this->schemaSql], - 'return' => $this->schemaStmt, - ], - [ - 'with' => [$this->tablesSql], - 'return' => $tablesStmt, - ], - [ - 'with' => [$this->columnsSql], - 'return' => false, - ], - [ - 'with' => [$this->indexSql], - 'return' => false, - ], - ]; - - $this->pdo->expects(static::exactly(count($statementMap))) + $this->pdo->expects(static::exactly(4)) ->method('prepare') - ->withConsecutive(...array_column($statementMap, 'with')) - ->willReturnOnConsecutiveCalls(...array_column($statementMap, 'return')); + ->willReturnMap([ + [$this->schemaSql, [], $this->schemaStmt], + [$this->tablesSql, [], $tablesStmt], + [$this->columnsSql, [], false], + [$this->indexSql, [], false], + ]); // Use the Factory to create the SchemaInfo $tableFilter = function (): bool { diff --git a/tests/SchemaInfoTest.php b/tests/SchemaInfoTest.php index 17941e3..5dabeb4 100644 --- a/tests/SchemaInfoTest.php +++ b/tests/SchemaInfoTest.php @@ -97,7 +97,7 @@ public function testGetTableInfo(): void { static::assertSame( $this->tableData[$this->tableName]['TABLE_INFO'], - $this->schemaInfo->getTableInfo($this->tableName) + $this->schemaInfo->getTableInfo($this->tableName), ); } @@ -124,7 +124,7 @@ public function testGetIndexInfo(): void { static::assertSame( $this->tableData[$this->tableName]['INDEXES']['PRIMARY'], - $this->schemaInfo->getIndexInfo($this->tableName, 'PRIMARY') + $this->schemaInfo->getIndexInfo($this->tableName, 'PRIMARY'), ); } @@ -151,7 +151,7 @@ public function testGetColumnInfo(): void { static::assertSame( $this->tableData[$this->tableName]['COLUMNS']['test_id'], - $this->schemaInfo->getColumnInfo($this->tableName, 'test_id') + $this->schemaInfo->getColumnInfo($this->tableName, 'test_id'), ); } }