modulesPath = base_path('modules'); $this->pluginsPath = base_path('plugins'); $this->templatesPath = base_path('templates'); // 모듈 fixture $this->createBundledModule('test-hidden-mod', true); $this->createBundledModule('test-visible-mod', false); // 플러그인 fixture $this->createBundledPlugin('test-hidden-plg', true); $this->createBundledPlugin('test-visible-plg', false); // 템플릿 fixture $this->createBundledTemplate('test-hidden-tpl', true); $this->createBundledTemplate('test-visible-tpl', false); Cache::flush(); ModuleManager::invalidateModuleStatusCache(); // 활성 디렉토리 보호 시작 (DB 시딩 이후) $this->setUpExtensionProtection(); } /** * 테스트 fixture 를 정리합니다. */ protected function tearDown(): void { $this->tearDownExtensionProtection(); $paths = [ $this->modulesPath.'/_bundled/test-hidden-mod', $this->modulesPath.'/_bundled/test-visible-mod', $this->pluginsPath.'/_bundled/test-hidden-plg', $this->pluginsPath.'/_bundled/test-visible-plg', $this->templatesPath.'/_bundled/test-hidden-tpl', $this->templatesPath.'/_bundled/test-visible-tpl', ]; foreach ($paths as $path) { if (File::isDirectory($path)) { File::deleteDirectory($path); } } Cache::flush(); Mockery::close(); parent::tearDown(); } /** * _bundled 테스트 모듈을 생성합니다. * * @param string $identifier 모듈 식별자 * @param bool $hidden hidden 플래그 값 */ private function createBundledModule(string $identifier, bool $hidden): void { $path = $this->modulesPath.'/_bundled/'.$identifier; File::ensureDirectoryExists($path); File::put($path.'/module.json', json_encode([ 'identifier' => $identifier, 'version' => '1.0.0', 'vendor' => 'test', 'name' => ['ko' => '테스트 '.$identifier, 'en' => 'Test '.$identifier], 'description' => ['ko' => 'hidden 플래그 테스트', 'en' => 'Hidden flag test'], 'dependencies' => [], 'hidden' => $hidden, ])); } /** * _bundled 테스트 플러그인을 생성합니다. * * @param string $identifier 플러그인 식별자 * @param bool $hidden hidden 플래그 값 */ private function createBundledPlugin(string $identifier, bool $hidden): void { $path = $this->pluginsPath.'/_bundled/'.$identifier; File::ensureDirectoryExists($path); File::put($path.'/plugin.json', json_encode([ 'identifier' => $identifier, 'version' => '1.0.0', 'vendor' => 'test', 'name' => ['ko' => '테스트 '.$identifier, 'en' => 'Test '.$identifier], 'description' => ['ko' => 'hidden 플래그 테스트', 'en' => 'Hidden flag test'], 'dependencies' => [], 'hidden' => $hidden, ])); } /** * _bundled 테스트 템플릿을 생성합니다. * * @param string $identifier 템플릿 식별자 * @param bool $hidden hidden 플래그 값 */ private function createBundledTemplate(string $identifier, bool $hidden): void { $path = $this->templatesPath.'/_bundled/'.$identifier; File::ensureDirectoryExists($path); File::put($path.'/template.json', json_encode([ 'identifier' => $identifier, 'version' => '1.0.0', 'vendor' => 'test', 'name' => ['ko' => '테스트 '.$identifier, 'en' => 'Test '.$identifier], 'description' => ['ko' => 'hidden 플래그 테스트', 'en' => 'Hidden flag test'], 'type' => 'admin', 'dependencies' => [], 'hidden' => $hidden, ])); } /** * ModuleManager 를 생성합니다. */ private function makeModuleManager(): ModuleManager { $moduleRepository = Mockery::mock(ModuleRepositoryInterface::class); $moduleRepository->shouldReceive('findByIdentifier')->andReturn(null)->byDefault(); $moduleRepository->shouldReceive('getAllKeyedByIdentifier') ->andReturn(collect()) ->byDefault(); return new ModuleManager( extensionManager: Mockery::mock(ExtensionManager::class), moduleRepository: $moduleRepository, permissionRepository: Mockery::mock(PermissionRepositoryInterface::class), roleRepository: Mockery::mock(RoleRepositoryInterface::class), menuRepository: Mockery::mock(MenuRepositoryInterface::class), templateRepository: Mockery::mock(TemplateRepositoryInterface::class), pluginRepository: Mockery::mock(PluginRepositoryInterface::class), layoutRepository: Mockery::mock(LayoutRepositoryInterface::class), layoutExtensionService: Mockery::mock(LayoutExtensionService::class), ); } /** * PluginManager 를 생성합니다. */ private function makePluginManager(): PluginManager { $pluginRepository = Mockery::mock(PluginRepositoryInterface::class); $pluginRepository->shouldReceive('findByIdentifier')->andReturn(null)->byDefault(); $pluginRepository->shouldReceive('getAllKeyedByIdentifier') ->andReturn(collect()) ->byDefault(); return new PluginManager( extensionManager: Mockery::mock(ExtensionManager::class), pluginRepository: $pluginRepository, permissionRepository: Mockery::mock(PermissionRepositoryInterface::class), roleRepository: Mockery::mock(RoleRepositoryInterface::class), templateRepository: Mockery::mock(TemplateRepositoryInterface::class), moduleRepository: Mockery::mock(ModuleRepositoryInterface::class), layoutRepository: Mockery::mock(LayoutRepositoryInterface::class), layoutExtensionService: Mockery::mock(LayoutExtensionService::class), ); } /** * TemplateManager 를 생성합니다. */ private function makeTemplateManager(): TemplateManager { $templateRepository = Mockery::mock(TemplateRepositoryInterface::class); $templateRepository->shouldReceive('getAllKeyedByIdentifier') ->andReturn(collect()) ->byDefault(); return new TemplateManager( extensionManager: Mockery::mock(ExtensionManager::class), templateRepository: $templateRepository, layoutRepository: Mockery::mock(LayoutRepositoryInterface::class), moduleRepository: Mockery::mock(ModuleRepositoryInterface::class), pluginRepository: Mockery::mock(PluginRepositoryInterface::class), layoutExtensionService: Mockery::mock(LayoutExtensionService::class), ); } // ======================================================================== // 모듈 // ======================================================================== /** * _bundled 모듈의 hidden 플래그가 ModuleManager 출력에 반영되는지 검증 */ public function test_module_manager_exposes_hidden_field(): void { $manager = $this->makeModuleManager(); $manager->loadModules(); $uninstalled = $manager->getUninstalledModules(); $this->assertArrayHasKey('test-hidden-mod', $uninstalled); $this->assertTrue($uninstalled['test-hidden-mod']['hidden']); $this->assertArrayHasKey('test-visible-mod', $uninstalled); $this->assertFalse($uninstalled['test-visible-mod']['hidden']); } /** * artisan module:list 가 기본적으로 hidden 모듈을 제외하는지 검증 */ public function test_module_list_command_hides_hidden_by_default(): void { $this->artisan('module:list') ->expectsOutputToContain('test-visible-mod') ->doesntExpectOutputToContain('test-hidden-mod') ->assertExitCode(0); } /** * artisan module:list --hidden 이 hidden 모듈을 포함해 출력하는지 검증 */ public function test_module_list_command_includes_hidden_with_flag(): void { $this->artisan('module:list', ['--hidden' => true]) ->expectsOutputToContain('test-hidden-mod') ->expectsOutputToContain('test-visible-mod') ->assertExitCode(0); } // ======================================================================== // 플러그인 // ======================================================================== /** * _bundled 플러그인의 hidden 플래그가 PluginManager 출력에 반영되는지 검증 */ public function test_plugin_manager_exposes_hidden_field(): void { $manager = $this->makePluginManager(); $manager->loadPlugins(); $uninstalled = $manager->getUninstalledPlugins(); $this->assertArrayHasKey('test-hidden-plg', $uninstalled); $this->assertTrue($uninstalled['test-hidden-plg']['hidden']); $this->assertArrayHasKey('test-visible-plg', $uninstalled); $this->assertFalse($uninstalled['test-visible-plg']['hidden']); } /** * artisan plugin:list 가 기본적으로 hidden 플러그인을 제외하는지 검증 */ public function test_plugin_list_command_hides_hidden_by_default(): void { $this->artisan('plugin:list') ->expectsOutputToContain('test-visible-plg') ->doesntExpectOutputToContain('test-hidden-plg') ->assertExitCode(0); } /** * artisan plugin:list --hidden 이 hidden 플러그인을 포함해 출력하는지 검증 */ public function test_plugin_list_command_includes_hidden_with_flag(): void { $this->artisan('plugin:list', ['--hidden' => true]) ->expectsOutputToContain('test-hidden-plg') ->expectsOutputToContain('test-visible-plg') ->assertExitCode(0); } // ======================================================================== // 템플릿 // ======================================================================== /** * _bundled 템플릿의 hidden 플래그가 TemplateManager 출력에 반영되는지 검증 */ public function test_template_manager_exposes_hidden_field(): void { $manager = $this->makeTemplateManager(); $manager->loadTemplates(); $uninstalled = $manager->getUninstalledTemplates(); $this->assertArrayHasKey('test-hidden-tpl', $uninstalled); $this->assertTrue($uninstalled['test-hidden-tpl']['hidden']); $this->assertArrayHasKey('test-visible-tpl', $uninstalled); $this->assertFalse($uninstalled['test-visible-tpl']['hidden']); } /** * artisan template:list 가 기본적으로 hidden 템플릿을 제외하는지 검증 */ public function test_template_list_command_hides_hidden_by_default(): void { $this->artisan('template:list') ->expectsOutputToContain('test-visible-tpl') ->doesntExpectOutputToContain('test-hidden-tpl') ->assertExitCode(0); } /** * artisan template:list --hidden 이 hidden 템플릿을 포함해 출력하는지 검증 */ public function test_template_list_command_includes_hidden_with_flag(): void { $this->artisan('template:list', ['--hidden' => true]) ->expectsOutputToContain('test-hidden-tpl') ->expectsOutputToContain('test-visible-tpl') ->assertExitCode(0); } }