Files
Gnuboard7/tests/Unit/Models/UserModelTest.php
T
2026-04-01 10:30:52 +09:00

452 lines
16 KiB
PHP

<?php
namespace Tests\Unit\Models;
use App\Enums\ExtensionOwnerType;
use App\Enums\PermissionType;
use App\Models\Permission;
use App\Models\Role;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
use PHPUnit\Framework\Attributes\Test;
/**
* User 모델 테스트
*
* User 모델의 is_super 필드 및 관련 메서드를 검증합니다.
*/
class UserModelTest extends TestCase
{
use RefreshDatabase;
// ========================================================================
// is_super 필드 테스트
// ========================================================================
/**
* is_super 필드가 fillable에 포함되어 있는지 확인
*/
public function test_is_super_is_in_fillable(): void
{
$user = new User();
$this->assertContains('is_super', $user->getFillable());
}
/**
* is_super 필드가 boolean으로 캐스팅되는지 확인
*/
public function test_is_super_is_cast_to_boolean(): void
{
$user = User::factory()->create(['is_super' => 1]);
$this->assertIsBool($user->is_super);
$this->assertTrue($user->is_super);
}
/**
* is_super 기본값이 false인지 확인
*/
public function test_is_super_defaults_to_false(): void
{
$user = User::factory()->create();
$this->assertFalse($user->is_super);
}
// ========================================================================
// isSuperAdmin() 메서드 테스트
// ========================================================================
/**
* is_super가 true인 사용자에서 isSuperAdmin()이 true 반환
*/
public function test_is_super_admin_returns_true_when_is_super_is_true(): void
{
$user = User::factory()->create(['is_super' => true]);
$this->assertTrue($user->isSuperAdmin());
}
/**
* is_super가 false인 사용자에서 isSuperAdmin()이 false 반환
*/
public function test_is_super_admin_returns_false_when_is_super_is_false(): void
{
$user = User::factory()->create(['is_super' => false]);
$this->assertFalse($user->isSuperAdmin());
}
/**
* is_super가 null인 사용자에서 isSuperAdmin()이 false 반환
*/
public function test_is_super_admin_returns_false_when_is_super_is_null(): void
{
$user = User::factory()->create();
// 직접 null로 설정 (DB에서 기본값이 false이지만 null 상황 테스트)
$user->is_super = null;
$this->assertFalse($user->isSuperAdmin());
}
// ========================================================================
// isAdmin() 메서드 테스트
// ========================================================================
/**
* admin 타입 권한을 가진 역할이 있으면 isAdmin()이 true 반환
*/
public function test_is_admin_returns_true_when_user_has_admin_type_permission(): void
{
// admin 타입 권한 생성
$adminPermission = Permission::create([
'identifier' => 'test.admin.permission',
'name' => ['ko' => '관리자 권한', 'en' => 'Admin Permission'],
'type' => PermissionType::Admin,
]);
// 역할 생성 및 권한 연결
$role = Role::create([
'identifier' => 'test-admin-role',
'name' => ['ko' => '테스트 관리자', 'en' => 'Test Admin'],
]);
$role->permissions()->attach($adminPermission->id);
// 사용자 생성 및 역할 연결
$user = User::factory()->create();
$user->roles()->attach($role->id);
$this->assertTrue($user->isAdmin());
}
/**
* user 타입 권한만 가진 경우 isAdmin()이 false 반환
*/
public function test_is_admin_returns_false_when_user_has_only_user_type_permission(): void
{
// user 타입 권한 생성
$userPermission = Permission::create([
'identifier' => 'test.user.permission',
'name' => ['ko' => '사용자 권한', 'en' => 'User Permission'],
'type' => PermissionType::User,
]);
// 역할 생성 및 권한 연결
$role = Role::create([
'identifier' => 'test-user-role',
'name' => ['ko' => '테스트 사용자', 'en' => 'Test User'],
]);
$role->permissions()->attach($userPermission->id);
// 사용자 생성 및 역할 연결
$user = User::factory()->create();
$user->roles()->attach($role->id);
$this->assertFalse($user->isAdmin());
}
/**
* 권한이 없는 사용자에서 isAdmin()이 false 반환
*/
public function test_is_admin_returns_false_when_user_has_no_permissions(): void
{
$user = User::factory()->create();
$this->assertFalse($user->isAdmin());
}
/**
* 역할이 없는 사용자에서 isAdmin()이 false 반환
*/
public function test_is_admin_returns_false_when_user_has_no_roles(): void
{
$user = User::factory()->create();
// 역할 없음 확인
$this->assertEquals(0, $user->roles()->count());
$this->assertFalse($user->isAdmin());
}
/**
* admin과 user 타입 권한을 모두 가진 경우 isAdmin()이 true 반환
*/
public function test_is_admin_returns_true_when_user_has_both_admin_and_user_permissions(): void
{
// admin 타입 권한
$adminPermission = Permission::create([
'identifier' => 'test.mixed.admin',
'name' => ['ko' => '관리자 권한', 'en' => 'Admin Permission'],
'type' => PermissionType::Admin,
]);
// user 타입 권한
$userPermission = Permission::create([
'identifier' => 'test.mixed.user',
'name' => ['ko' => '사용자 권한', 'en' => 'User Permission'],
'type' => PermissionType::User,
]);
// 역할 생성 및 두 권한 모두 연결
$role = Role::create([
'identifier' => 'test-mixed-role',
'name' => ['ko' => '혼합 역할', 'en' => 'Mixed Role'],
]);
$role->permissions()->attach([$adminPermission->id, $userPermission->id]);
// 사용자 생성 및 역할 연결
$user = User::factory()->create();
$user->roles()->attach($role->id);
$this->assertTrue($user->isAdmin());
}
// ========================================================================
// scopeSuperAdmins() 스코프 테스트
// ========================================================================
/**
* superAdmins() 스코프가 is_super=true인 사용자만 조회하는지 확인
*/
public function test_super_admins_scope_returns_only_super_admins(): void
{
// 슈퍼 관리자 2명 생성
User::factory()->create(['is_super' => true, 'email' => 'super1@test.com']);
User::factory()->create(['is_super' => true, 'email' => 'super2@test.com']);
// 일반 사용자 3명 생성
User::factory()->create(['is_super' => false, 'email' => 'user1@test.com']);
User::factory()->create(['is_super' => false, 'email' => 'user2@test.com']);
User::factory()->create(['is_super' => false, 'email' => 'user3@test.com']);
$superAdmins = User::superAdmins()->get();
$this->assertCount(2, $superAdmins);
$superAdmins->each(function ($user) {
$this->assertTrue($user->is_super);
});
}
/**
* 슈퍼 관리자가 없으면 빈 컬렉션 반환
*/
#[Test]
public function test_super_admins_scope_returns_empty_when_no_super_admins(): void
{
// 일반 사용자만 생성
User::factory()->count(3)->create(['is_super' => false]);
$superAdmins = User::superAdmins()->get();
$this->assertCount(0, $superAdmins);
}
// ========================================================================
// 복합 시나리오 테스트
// ========================================================================
/**
* 슈퍼 관리자이면서 관리자 권한도 가진 사용자 테스트
*/
public function test_user_can_be_both_super_admin_and_have_admin_permissions(): void
{
// admin 타입 권한 생성
$adminPermission = Permission::create([
'identifier' => 'core.users.read',
'name' => ['ko' => '사용자 조회', 'en' => 'Read Users'],
'extension_type' => ExtensionOwnerType::Core,
'extension_identifier' => 'core',
'type' => PermissionType::Admin,
]);
// 역할 생성 및 권한 연결
$role = Role::create([
'identifier' => 'admin',
'name' => ['ko' => '관리자', 'en' => 'Administrator'],
'extension_type' => ExtensionOwnerType::Core,
'extension_identifier' => 'core',
]);
$role->permissions()->attach($adminPermission->id);
// 슈퍼 관리자 생성 및 역할 연결
$user = User::factory()->create(['is_super' => true]);
$user->roles()->attach($role->id);
$this->assertTrue($user->isSuperAdmin());
$this->assertTrue($user->isAdmin());
}
/**
* 일반 관리자(is_super=false)이지만 관리자 권한은 가진 사용자 테스트
*/
public function test_regular_admin_has_admin_permissions_but_not_super(): void
{
// admin 타입 권한 생성
$adminPermission = Permission::create([
'identifier' => 'core.settings.read',
'name' => ['ko' => '설정 조회', 'en' => 'Read Settings'],
'extension_type' => ExtensionOwnerType::Core,
'extension_identifier' => 'core',
'type' => PermissionType::Admin,
]);
// 역할 생성 및 권한 연결
$role = Role::create([
'identifier' => 'manager',
'name' => ['ko' => '매니저', 'en' => 'Manager'],
]);
$role->permissions()->attach($adminPermission->id);
// 일반 관리자 생성 (is_super=false)
$user = User::factory()->create(['is_super' => false]);
$user->roles()->attach($role->id);
$this->assertFalse($user->isSuperAdmin());
$this->assertTrue($user->isAdmin());
}
// ========================================================================
// hasPermission() 메서드 type 파라미터 테스트
// ========================================================================
/**
* hasPermission()에서 type을 지정하면 해당 타입의 권한만 체크합니다.
*/
public function test_has_permission_with_type_checks_specific_type(): void
{
// admin 타입 권한 생성
$adminPermission = Permission::create([
'identifier' => 'test.permission',
'name' => ['ko' => '테스트 권한', 'en' => 'Test Permission'],
'type' => PermissionType::Admin,
]);
// 역할 생성 및 권한 연결
$role = Role::create([
'identifier' => 'test-role',
'name' => ['ko' => '테스트 역할', 'en' => 'Test Role'],
]);
$role->permissions()->attach($adminPermission->id);
// 사용자 생성 및 역할 연결
$user = User::factory()->create();
$user->roles()->attach($role->id);
// admin 타입으로 체크하면 true
$this->assertTrue($user->hasPermission('test.permission', PermissionType::Admin));
// user 타입으로 체크하면 false
$this->assertFalse($user->hasPermission('test.permission', PermissionType::User));
// type 없이 체크하면 true (기존 동작 유지)
$this->assertTrue($user->hasPermission('test.permission'));
}
/**
* hasPermission()에서 type을 null로 지정하면 모든 타입을 체크합니다.
*/
public function test_has_permission_without_type_checks_all_types(): void
{
// user 타입 권한 생성
$userPermission = Permission::create([
'identifier' => 'test.user.only',
'name' => ['ko' => '사용자 전용 권한', 'en' => 'User Only Permission'],
'type' => PermissionType::User,
]);
// 역할 생성 및 권한 연결
$role = Role::create([
'identifier' => 'user-role',
'name' => ['ko' => '사용자 역할', 'en' => 'User Role'],
]);
$role->permissions()->attach($userPermission->id);
// 사용자 생성 및 역할 연결
$user = User::factory()->create();
$user->roles()->attach($role->id);
// type 없이 체크하면 true
$this->assertTrue($user->hasPermission('test.user.only'));
$this->assertTrue($user->hasPermission('test.user.only', null));
}
// ========================================================================
// hasPermissions() 메서드 type 파라미터 테스트
// ========================================================================
/**
* hasPermissions()에서 type을 지정하면 해당 타입의 권한만 체크합니다.
*/
public function test_has_permissions_with_type_checks_specific_type(): void
{
// admin 타입 권한 2개 생성
$adminPerm1 = Permission::create([
'identifier' => 'admin.perm1',
'name' => ['ko' => '관리자 권한1', 'en' => 'Admin Permission 1'],
'type' => PermissionType::Admin,
]);
$adminPerm2 = Permission::create([
'identifier' => 'admin.perm2',
'name' => ['ko' => '관리자 권한2', 'en' => 'Admin Permission 2'],
'type' => PermissionType::Admin,
]);
// 역할 생성 및 권한 연결
$role = Role::create([
'identifier' => 'multi-admin-role',
'name' => ['ko' => '다중 권한 역할', 'en' => 'Multi Permission Role'],
]);
$role->permissions()->attach([$adminPerm1->id, $adminPerm2->id]);
// 사용자 생성 및 역할 연결
$user = User::factory()->create();
$user->roles()->attach($role->id);
// admin 타입으로 AND 체크
$this->assertTrue(
$user->hasPermissions(['admin.perm1', 'admin.perm2'], true, PermissionType::Admin)
);
// user 타입으로 체크하면 실패
$this->assertFalse(
$user->hasPermissions(['admin.perm1', 'admin.perm2'], true, PermissionType::User)
);
}
/**
* hasPermissions()에서 OR 로직과 type을 함께 사용합니다.
*/
public function test_has_permissions_with_or_logic_and_type(): void
{
// admin 타입 권한 1개만 생성
$adminPerm = Permission::create([
'identifier' => 'admin.single',
'name' => ['ko' => '단일 관리자 권한', 'en' => 'Single Admin Permission'],
'type' => PermissionType::Admin,
]);
// 역할 생성 및 권한 연결
$role = Role::create([
'identifier' => 'single-perm-role',
'name' => ['ko' => '단일 권한 역할', 'en' => 'Single Permission Role'],
]);
$role->permissions()->attach($adminPerm->id);
// 사용자 생성 및 역할 연결
$user = User::factory()->create();
$user->roles()->attach($role->id);
// OR 로직으로 admin 타입 체크 - 하나만 있어도 true
$this->assertTrue(
$user->hasPermissions(['admin.single', 'admin.nonexistent'], false, PermissionType::Admin)
);
// OR 로직으로 user 타입 체크 - 해당 권한 없으므로 false
$this->assertFalse(
$user->hasPermissions(['admin.single', 'admin.nonexistent'], false, PermissionType::User)
);
}
}