getHookListeners(); // 모듈 리스너 목록에 등록 → 미설치(모듈 비활성) 시 자동 미등록 $this->assertContains(UserCurrencyInfoListener::class, $listeners); $this->assertContains(AssignDefaultCurrencyOnRegisterListener::class, $listeners); } public function test_admin_currency_field_is_layout_extension(): void { // 관리자 통화 필드는 코어 폼 하드코딩이 아니라 모듈 layout_extension JSON 으로 주입 $extPath = dirname(__DIR__, 2).'/resources/extensions/admin-user-currency-field.json'; $this->assertFileExists($extPath); $ext = json_decode(file_get_contents($extPath), true); $this->assertSame('admin_user_form', $ext['target_layout']); // 코어 확장 슬롯(extension_form_content)으로 주입 — 코어 폼 본체 미변경 $this->assertSame('extension_form_content', $ext['injections'][0]['target_id']); } public function test_user_profile_table_is_module_migration(): void { // user-profile 테이블은 모듈 마이그레이션 → 미설치 시 테이블 부재 $migrationPath = dirname(__DIR__, 2).'/database/migrations'; $files = glob($migrationPath.'/*_create_ecommerce_user_profiles_table.php'); $this->assertNotEmpty($files, 'ecommerce_user_profiles 마이그레이션이 모듈에 존재해야 합니다.'); } public function test_user_currency_permission_is_module_owned(): void { $module = new Module; $permissions = $module->getPermissions(); $identifiers = collect($permissions['categories'] ?? [])->pluck('identifier')->all(); $this->assertContains('user-currency', $identifiers, '회원 통화 관리 권한이 모듈에 정의되어야 합니다.'); } }