testDir = sys_get_temp_dir() . '/route_test_' . uniqid(); mkdir($this->testDir, 0777, true); // Create route directory mkdir($this->testDir . '/route', 0777, true); // Create mock SymfonyStyle $this->io = $this->createMock(SymfonyStyle::class); $this->routeUpdater = new RouteUpdater(); } protected function tearDown(): void { if (is_dir($this->testDir)) { $this->removeDirectory($this->testDir); } } private function removeDirectory($dir) { if (!is_dir($dir)) { return; } $items = scandir($dir); foreach ($items as $item) { if ($item != '.' && $item != '..') { $path = $dir . DIRECTORY_SEPARATOR . $item; if (is_dir($path)) { $this->removeDirectory($path); } else { unlink($path); } } } rmdir($dir); } public function testUpdateRoutesWithBothFiles() { // Create initial route files file_put_contents($this->testDir . '/route/api.php', "testDir . '/route/admin.php', " 'TestExtension', 'name' => 'test-extension' ]; $this->io->expects($this->exactly(2)) ->method('text') ->with($this->logicalOr( $this->stringContains('更新API路由文件'), $this->stringContains('更新Admin路由文件') )); $result = $this->routeUpdater->updateRoutes( $tableName, $tableComment, $extensionInfo, $this->testDir, $this->io ); $this->assertTrue($result); // Check API routes file $apiContent = file_get_contents($this->testDir . '/route/api.php'); $this->assertStringContainsString('Route::resource(\'users\', TestExtension\\Controller\\Api\\UserController::class);', $apiContent); $this->assertStringContainsString('User management table相关路由', $apiContent); // Check Admin routes file $adminContent = file_get_contents($this->testDir . '/route/admin.php'); $this->assertStringContainsString('Route::resource(\'users\', TestExtension\\Controller\\Admin\\UserController::class);', $adminContent); $this->assertStringContainsString('User management table管理路由', $adminContent); } public function testUpdateRoutesWithMissingFiles() { $tableName = 'products'; $tableComment = 'Product table'; $extensionInfo = [ 'namespace' => 'TestExtension', 'name' => 'test-extension' ]; $this->io->expects($this->exactly(2)) ->method('warning') ->with($this->logicalOr( $this->stringContains('API路由文件不存在'), $this->stringContains('Admin路由文件不存在') )); $result = $this->routeUpdater->updateRoutes( $tableName, $tableComment, $extensionInfo, $this->testDir, $this->io ); $this->assertTrue($result); // Should still return true when files don't exist } public function testUpdateRoutesWithExistingRoutes() { // Create route files with existing routes $existingApiContent = "testDir . '/route/api.php', $existingApiContent); file_put_contents($this->testDir . '/route/admin.php', $existingAdminContent); $tableName = 'users'; $tableComment = 'User table'; $extensionInfo = [ 'namespace' => 'TestExtension', 'name' => 'test-extension' ]; $this->io->expects($this->exactly(2)) ->method('text') ->with($this->logicalOr( $this->stringContains('API路由已存在'), $this->stringContains('Admin路由已存在') )); $result = $this->routeUpdater->updateRoutes( $tableName, $tableComment, $extensionInfo, $this->testDir, $this->io ); $this->assertTrue($result); // Verify content wasn't duplicated $apiContent = file_get_contents($this->testDir . '/route/api.php'); $this->assertEquals(1, substr_count($apiContent, 'Route::resource(\'users\'')); $adminContent = file_get_contents($this->testDir . '/route/admin.php'); $this->assertEquals(1, substr_count($adminContent, 'Route::resource(\'users\'')); } public function testTableNameConversion() { // Test various table name formats $testCases = [ 'user_profiles' => ['UserProfileController', 'user_profiles'], 'tbl_products' => ['ProductController', 'products'], 'blog_posts' => ['BlogPostController', 'blog_posts'], 'categories' => ['CategoryController', 'categories'], 'tb_orders' => ['OrderController', 'orders'] ]; foreach ($testCases as $tableName => [$expectedController, $expectedResource]) { // Create fresh route files for each test file_put_contents($this->testDir . '/route/api.php', " 'TestExtension', 'name' => 'test-extension' ]; $this->routeUpdater->updateRoutes( $tableName, 'Test table', $extensionInfo, $this->testDir, $this->io ); $apiContent = file_get_contents($this->testDir . '/route/api.php'); $this->assertStringContainsString("Route::resource('{$expectedResource}', TestExtension\\Controller\\Api\\{$expectedController}::class);", $apiContent); } } public function testNamespaceHandling() { file_put_contents($this->testDir . '/route/api.php', "testDir . '/route/admin.php', " $namespace, 'name' => 'test-extension' ]; $this->routeUpdater->updateRoutes( $tableName, $tableComment, $extensionInfo, $this->testDir, $this->io ); $apiContent = file_get_contents($this->testDir . '/route/api.php'); $this->assertStringContainsString("{$namespace}\\Controller\\Api\\PostController::class", $apiContent); $adminContent = file_get_contents($this->testDir . '/route/admin.php'); $this->assertStringContainsString("{$namespace}\\Controller\\Admin\\PostController::class", $adminContent); // Reset files for next iteration file_put_contents($this->testDir . '/route/api.php', "testDir . '/route/admin.php', "testDir . '/route/api.php', "testDir . '/route/admin.php', " 'Blog\\Extension', 'name' => 'blog-extension' ]; $result = $this->routeUpdater->updateRoutes( $tableName, $tableComment, $extensionInfo, $this->testDir, $this->io ); $this->assertTrue($result); // Check API route structure $apiContent = file_get_contents($this->testDir . '/route/api.php'); $this->assertStringContainsString('// Article management相关路由', $apiContent); $this->assertStringContainsString('Route::resource(\'articles\', Blog\\Extension\\Controller\\Api\\ArticleController::class);', $apiContent); // Check Admin route structure $adminContent = file_get_contents($this->testDir . '/route/admin.php'); $this->assertStringContainsString('// Article management管理路由', $adminContent); $this->assertStringContainsString('Route::resource(\'articles\', Blog\\Extension\\Controller\\Admin\\ArticleController::class);', $adminContent); } public function testErrorHandling() { // Create a read-only route file to trigger write error file_put_contents($this->testDir . '/route/api.php', "testDir . '/route/api.php', 0444); // Read-only $tableName = 'users'; $tableComment = 'User table'; $extensionInfo = [ 'namespace' => 'TestExtension', 'name' => 'test-extension' ]; $this->io->expects($this->once()) ->method('error') ->with($this->stringContains('无法写入API路由文件')); $result = $this->routeUpdater->updateRoutes( $tableName, $tableComment, $extensionInfo, $this->testDir, $this->io ); $this->assertFalse($result); // Restore permissions for cleanup chmod($this->testDir . '/route/api.php', 0644); } public function testFileContentAppending() { $initialApiContent = "testDir . '/route/api.php', $initialApiContent); file_put_contents($this->testDir . '/route/admin.php', $initialAdminContent); $tableName = 'comments'; $tableComment = 'Comment management'; $extensionInfo = [ 'namespace' => 'BlogExtension', 'name' => 'blog-extension' ]; $result = $this->routeUpdater->updateRoutes( $tableName, $tableComment, $extensionInfo, $this->testDir, $this->io ); $this->assertTrue($result); // Check that original content is preserved and new content is appended $apiContent = file_get_contents($this->testDir . '/route/api.php'); $this->assertStringContainsString('Route::get(\'/test\', \'TestController@test\');', $apiContent); $this->assertStringContainsString('Route::resource(\'comments\', BlogExtension\\Controller\\Api\\CommentController::class);', $apiContent); $adminContent = file_get_contents($this->testDir . '/route/admin.php'); $this->assertStringContainsString('Route::get(\'/admin-test\', \'AdminTestController@test\');', $adminContent); $this->assertStringContainsString('Route::resource(\'comments\', BlogExtension\\Controller\\Admin\\CommentController::class);', $adminContent); } public function testMultipleResourceUpdates() { file_put_contents($this->testDir . '/route/api.php', " 'TestExtension', 'name' => 'test-extension' ]; foreach ($resources as [$tableName, $tableComment]) { $result = $this->routeUpdater->updateRoutes( $tableName, $tableComment, $extensionInfo, $this->testDir, $this->io ); $this->assertTrue($result); } $apiContent = file_get_contents($this->testDir . '/route/api.php'); // Verify all resources are added $this->assertStringContainsString('Route::resource(\'users\', TestExtension\\Controller\\Api\\UserController::class);', $apiContent); $this->assertStringContainsString('Route::resource(\'posts\', TestExtension\\Controller\\Api\\PostController::class);', $apiContent); $this->assertStringContainsString('Route::resource(\'categories\', TestExtension\\Controller\\Api\\CategoryController::class);', $apiContent); } }