BREAKING CHANGE: Requires PHP 8.5.0RC3 Changes: - Update Docker base image from php:8.4-fpm to php:8.5.0RC3-fpm - Enable ext-uri for native WHATWG URL parsing support - Update composer.json PHP requirement from ^8.4 to ^8.5 - Add ext-uri as required extension in composer.json - Move URL classes from Url.php85/ to Url/ directory (now compatible) - Remove temporary PHP 8.4 compatibility workarounds Benefits: - Native URL parsing with Uri\WhatWg\Url class - Better performance for URL operations - Future-proof with latest PHP features - Eliminates PHP version compatibility issues
175 lines
6.0 KiB
PHP
175 lines
6.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Framework\Database\Migration;
|
|
|
|
use App\Framework\Core\ValueObjects\ClassName;
|
|
use App\Framework\Database\Migration\Migration;
|
|
use App\Framework\Database\Migration\MigrationCollection;
|
|
use App\Framework\Database\Migration\MigrationLoader;
|
|
use App\Framework\Database\Migration\MigrationVersion;
|
|
use App\Framework\DI\Container;
|
|
use App\Framework\Discovery\Results\AttributeRegistry;
|
|
use App\Framework\Discovery\Results\DiscoveryRegistry;
|
|
use App\Framework\Discovery\Results\InterfaceRegistry;
|
|
use App\Framework\Discovery\Results\TemplateRegistry;
|
|
use App\Framework\Discovery\ValueObjects\InterfaceMapping;
|
|
use App\Framework\Filesystem\ValueObjects\FilePath;
|
|
use PHPUnit\Framework\Attributes\Test;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
final class MigrationLoaderTest extends TestCase
|
|
{
|
|
private Container $container;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->container = $this->createMock(Container::class);
|
|
}
|
|
|
|
#[Test]
|
|
public function loadMigrations_returns_empty_collection_when_no_migrations_found(): void
|
|
{
|
|
// Setup interface registry with no migrations
|
|
$interfaceRegistry = new InterfaceRegistry();
|
|
|
|
$discoveryRegistry = new DiscoveryRegistry(
|
|
new AttributeRegistry(),
|
|
$interfaceRegistry,
|
|
new TemplateRegistry()
|
|
);
|
|
|
|
$loader = new MigrationLoader($discoveryRegistry, $this->container);
|
|
|
|
$result = $loader->loadMigrations();
|
|
|
|
$this->assertInstanceOf(MigrationCollection::class, $result);
|
|
$this->assertTrue($result->isEmpty());
|
|
$this->assertSame(0, $result->count());
|
|
}
|
|
|
|
#[Test]
|
|
public function loadMigrations_returns_sorted_collection_of_migrations(): void
|
|
{
|
|
// Create mock migration instances (in unsorted order)
|
|
$migration1 = $this->createMockMigration('2024_01_03_120000', 'Third migration');
|
|
$migration2 = $this->createMockMigration('2024_01_01_120000', 'First migration');
|
|
$migration3 = $this->createMockMigration('2024_01_02_120000', 'Second migration');
|
|
|
|
// Create interface mappings
|
|
$mapping1 = new InterfaceMapping(
|
|
ClassName::create(Migration::class),
|
|
ClassName::create('App\\Migration1'),
|
|
FilePath::create('/path/to/migration1.php')
|
|
);
|
|
$mapping2 = new InterfaceMapping(
|
|
ClassName::create(Migration::class),
|
|
ClassName::create('App\\Migration2'),
|
|
FilePath::create('/path/to/migration2.php')
|
|
);
|
|
$mapping3 = new InterfaceMapping(
|
|
ClassName::create(Migration::class),
|
|
ClassName::create('App\\Migration3'),
|
|
FilePath::create('/path/to/migration3.php')
|
|
);
|
|
|
|
// Setup interface registry
|
|
$interfaceRegistry = new InterfaceRegistry();
|
|
$interfaceRegistry->add($mapping1);
|
|
$interfaceRegistry->add($mapping2);
|
|
$interfaceRegistry->add($mapping3);
|
|
|
|
$discoveryRegistry = new DiscoveryRegistry(
|
|
new AttributeRegistry(),
|
|
$interfaceRegistry,
|
|
new TemplateRegistry()
|
|
);
|
|
|
|
$loader = new MigrationLoader($discoveryRegistry, $this->container);
|
|
|
|
// Setup container to return migration instances
|
|
$this->container->method('get')
|
|
->willReturnMap([
|
|
['App\\Migration1', $migration1],
|
|
['App\\Migration2', $migration2],
|
|
['App\\Migration3', $migration3],
|
|
]);
|
|
|
|
$result = $loader->loadMigrations();
|
|
|
|
$this->assertInstanceOf(MigrationCollection::class, $result);
|
|
$this->assertSame(3, $result->count());
|
|
|
|
// Verify migrations are sorted by version
|
|
$migrations = $result->toArray();
|
|
$this->assertSame($migration2, $migrations[0]); // 2024_01_01_120000
|
|
$this->assertSame($migration3, $migrations[1]); // 2024_01_02_120000
|
|
$this->assertSame($migration1, $migrations[2]); // 2024_01_03_120000
|
|
}
|
|
|
|
#[Test]
|
|
public function loadMigrations_uses_discovery_registry_to_find_migration_implementations(): void
|
|
{
|
|
$interfaceRegistry = new InterfaceRegistry();
|
|
|
|
$discoveryRegistry = new DiscoveryRegistry(
|
|
new AttributeRegistry(),
|
|
$interfaceRegistry,
|
|
new TemplateRegistry()
|
|
);
|
|
|
|
$loader = new MigrationLoader($discoveryRegistry, $this->container);
|
|
|
|
$result = $loader->loadMigrations();
|
|
|
|
// Verify that the discovery registry was used by checking we get an empty collection
|
|
$this->assertInstanceOf(MigrationCollection::class, $result);
|
|
$this->assertTrue($result->isEmpty());
|
|
}
|
|
|
|
#[Test]
|
|
public function loadMigrations_uses_container_to_instantiate_migrations(): void
|
|
{
|
|
$migration = $this->createMockMigration('2024_01_01_120000', 'Test migration');
|
|
|
|
$mapping = new InterfaceMapping(
|
|
ClassName::create(Migration::class),
|
|
ClassName::create('App\\TestMigration'),
|
|
FilePath::create('/path/to/test_migration.php')
|
|
);
|
|
|
|
$interfaceRegistry = new InterfaceRegistry();
|
|
$interfaceRegistry->add($mapping);
|
|
|
|
$discoveryRegistry = new DiscoveryRegistry(
|
|
new AttributeRegistry(),
|
|
$interfaceRegistry,
|
|
new TemplateRegistry()
|
|
);
|
|
|
|
$loader = new MigrationLoader($discoveryRegistry, $this->container);
|
|
|
|
$this->container->expects($this->once())
|
|
->method('get')
|
|
->with('App\\TestMigration')
|
|
->willReturn($migration);
|
|
|
|
$result = $loader->loadMigrations();
|
|
|
|
$this->assertSame(1, $result->count());
|
|
$this->assertSame($migration, $result->toArray()[0]);
|
|
}
|
|
|
|
private function createMockMigration(string $version, string $description): Migration
|
|
{
|
|
$migration = $this->createMock(Migration::class);
|
|
$migration->method('getVersion')
|
|
->willReturn(MigrationVersion::fromTimestamp($version));
|
|
$migration->method('getDescription')
|
|
->willReturn($description);
|
|
|
|
return $migration;
|
|
}
|
|
}
|