generator = new IndexMigrationGenerator($connection); }); it('generates migration for adding indexes', function () { $recommendations = [ new IndexRecommendation( tableName: 'users', columns: ['email'], indexType: IndexType::BTREE, reason: 'Frequent WHERE email lookups', priority: RecommendationPriority::HIGH, estimatedSpeedup: 5.0, affectedQueries: 100 ), new IndexRecommendation( tableName: 'users', columns: ['status', 'created_at'], indexType: IndexType::BTREE, reason: 'WHERE status + ORDER BY created_at', priority: RecommendationPriority::CRITICAL, estimatedSpeedup: 10.0, affectedQueries: 250 ) ]; $migration = $this->generator->generateAddIndexMigration($recommendations, 'users'); expect($migration)->toBeString(); expect($migration)->toContain('extends Migration'); expect($migration)->toContain('public function up(Schema $schema)'); expect($migration)->toContain('public function down(Schema $schema)'); expect($migration)->toContain('users'); expect($migration)->toContain('$table->index'); }); it('generates migration for removing indexes', function () { $unusedIndexes = [ [ 'index_name' => 'idx_users_old_column', 'columns' => ['old_column'] ], [ 'index_name' => 'idx_users_deprecated', 'columns' => ['deprecated_field'] ] ]; $migration = $this->generator->generateRemoveIndexMigration($unusedIndexes, 'users'); expect($migration)->toBeString(); expect($migration)->toContain('extends Migration'); expect($migration)->toContain('$table->dropIndex'); expect($migration)->toContain('idx_users_old_column'); expect($migration)->toContain('idx_users_deprecated'); }); it('generates optimization migration (add + remove)', function () { $toAdd = [ new IndexRecommendation( tableName: 'orders', columns: ['customer_id', 'status'], indexType: IndexType::BTREE, reason: 'WHERE customer_id + status filter', priority: RecommendationPriority::HIGH, estimatedSpeedup: 8.0, affectedQueries: 150 ) ]; $toRemove = [ [ 'index_name' => 'idx_orders_unused', 'columns' => ['unused_column'] ] ]; $migration = $this->generator->generateOptimizationMigration($toAdd, $toRemove, 'orders'); expect($migration)->toBeString(); expect($migration)->toContain('extends Migration'); expect($migration)->toContain('$table->dropIndex(\'idx_orders_unused\')'); expect($migration)->toContain('$table->index'); }); it('includes proper up/down migration methods', function () { $recommendations = [ new IndexRecommendation( tableName: 'products', columns: ['category'], indexType: IndexType::BTREE, reason: 'Category filtering', priority: RecommendationPriority::MEDIUM, estimatedSpeedup: 3.0, affectedQueries: 50 ) ]; $migration = $this->generator->generateAddIndexMigration($recommendations, 'products'); // Check UP method expect($migration)->toContain('public function up(Schema $schema)'); expect($migration)->toContain('$schema->table(\'products\''); // Check DOWN method (should reverse the UP actions) expect($migration)->toContain('public function down(Schema $schema)'); expect($migration)->toContain('$table->dropIndex'); }); it('validates migration content structure', function () { $recommendations = [ new IndexRecommendation( tableName: 'test_table', columns: ['test_column'], indexType: IndexType::BTREE, reason: 'Test', priority: RecommendationPriority::LOW, estimatedSpeedup: 1.5, affectedQueries: 10 ) ]; $migration = $this->generator->generateAddIndexMigration($recommendations, 'test_table'); // Validate required components expect($migration)->toContain('declare(strict_types=1)'); expect($migration)->toContain('use App\Framework\Database\Migration\Migration'); expect($migration)->toContain('use App\Framework\Database\Schema\Schema'); expect($migration)->toContain('final class'); }); it('handles composite indexes correctly', function () { $recommendations = [ new IndexRecommendation( tableName: 'posts', columns: ['author_id', 'published_at', 'status'], indexType: IndexType::BTREE, reason: 'Complex WHERE + ORDER BY', priority: RecommendationPriority::CRITICAL, estimatedSpeedup: 15.0, affectedQueries: 300 ) ]; $migration = $this->generator->generateAddIndexMigration($recommendations, 'posts'); expect($migration)->toContain('author_id'); expect($migration)->toContain('published_at'); expect($migration)->toContain('status'); }); });