Files
biiproject-kit-v1/tests/Feature/AccessControl/RoleManagementTest.php
T

194 lines
6.3 KiB
PHP

<?php
use App\Models\Permission;
use App\Models\Role;
use App\Models\User;
use Illuminate\Foundation\Testing\WithFaker;
uses(WithFaker::class);
function grantManageAccessRights(User $user): void
{
$perm = Permission::firstOrCreate(['name' => 'manage access rights', 'guard_name' => 'web']);
Permission::firstOrCreate(['name' => 'view access rights', 'guard_name' => 'web']);
$user->givePermissionTo($perm);
}
test('guest cannot access roles index', function () {
$this->get('/roles')->assertRedirect('/login');
});
test('authenticated user without permission gets 403 on roles index', function () {
$user = User::factory()->create();
$this->actingAs($user)->get('/roles')->assertForbidden();
});
test('user with manage access rights can store a new role', function () {
$user = User::factory()->create();
grantManageAccessRights($user);
$p = Permission::firstOrCreate(['name' => 'view dashboard', 'guard_name' => 'web']);
$response = $this->actingAs($user)
->postJson('/roles', [
'name' => 'editor-role',
'guard_name' => 'web',
'permissions' => [$p->id],
]);
$response->assertOk()->assertJson(['success' => true]);
$this->assertDatabaseHas('roles', ['name' => 'editor-role']);
$role = Role::where('name', 'editor-role')->first();
expect($role->hasPermissionTo('view dashboard'))->toBeTrue();
});
test('store rejects duplicate role name', function () {
$user = User::factory()->create();
grantManageAccessRights($user);
$p = Permission::firstOrCreate(['name' => 'view dashboard', 'guard_name' => 'web']);
Role::create(['name' => 'dup-role', 'guard_name' => 'web']);
$response = $this->actingAs($user)
->postJson('/roles', [
'name' => 'dup-role',
'guard_name' => 'web',
'permissions' => [$p->id],
]);
$response->assertStatus(422);
});
test('store rejects empty permissions array', function () {
$user = User::factory()->create();
grantManageAccessRights($user);
$response = $this->actingAs($user)
->postJson('/roles', [
'name' => 'no-perm-role',
'guard_name' => 'web',
'permissions' => [],
]);
$response->assertStatus(422);
});
test('store rejects invalid characters in role name', function () {
$user = User::factory()->create();
grantManageAccessRights($user);
$p = Permission::firstOrCreate(['name' => 'view dashboard', 'guard_name' => 'web']);
$response = $this->actingAs($user)
->postJson('/roles', [
'name' => 'role with space!',
'guard_name' => 'web',
'permissions' => [$p->id],
]);
$response->assertStatus(422);
});
test('update replaces role permissions', function () {
$user = User::factory()->create();
grantManageAccessRights($user);
$p1 = Permission::firstOrCreate(['name' => 'view dashboard', 'guard_name' => 'web']);
$p2 = Permission::firstOrCreate(['name' => 'view user directory', 'guard_name' => 'web']);
$role = Role::create(['name' => 'original-role', 'guard_name' => 'web']);
$role->givePermissionTo('view dashboard');
$response = $this->actingAs($user)
->putJson("/roles/{$role->id}", [
'name' => 'renamed-role',
'guard_name' => 'web',
'permissions' => [$p2->id],
]);
$response->assertOk();
$role->refresh();
expect($role->name)->toBe('renamed-role');
expect($role->hasPermissionTo('view user directory'))->toBeTrue();
expect($role->hasPermissionTo('view dashboard'))->toBeFalse();
});
test('toggleStatus activates and deactivates role', function () {
$user = User::factory()->create();
grantManageAccessRights($user);
$role = Role::create(['name' => 'toggleable', 'guard_name' => 'web', 'is_active' => true]);
$this->actingAs($user)
->postJson('/roles/toggle-status', ['id' => $role->id, 'status' => 'deactivate'])
->assertOk();
expect((bool) $role->fresh()->is_active)->toBeFalse();
$this->actingAs($user)
->postJson('/roles/toggle-status', ['id' => $role->id, 'status' => 'activate'])
->assertOk();
expect((bool) $role->fresh()->is_active)->toBeTrue();
});
test('destroy soft deletes role when no users assigned', function () {
$user = User::factory()->create();
grantManageAccessRights($user);
$role = Role::create(['name' => 'doomed', 'guard_name' => 'web']);
$this->actingAs($user)
->deleteJson("/roles/{$role->id}")
->assertOk();
expect(Role::withTrashed()->find($role->id)->trashed())->toBeTrue();
});
test('destroy blocks deletion when role is still assigned to a user', function () {
$admin = User::factory()->create();
grantManageAccessRights($admin);
$role = Role::create(['name' => 'in-use', 'guard_name' => 'web']);
$victim = User::factory()->create();
$victim->assignRole($role);
$this->actingAs($admin)
->deleteJson("/roles/{$role->id}")
->assertStatus(422)
->assertJson(['success' => false]);
expect(Role::find($role->id))->not->toBeNull();
});
test('restore brings back a soft-deleted role', function () {
$user = User::factory()->create();
grantManageAccessRights($user);
$role = Role::create(['name' => 'restorable', 'guard_name' => 'web']);
$role->delete();
$this->actingAs($user)
->postJson("/roles/{$role->id}/restore")
->assertOk();
expect(Role::find($role->id)->trashed())->toBeFalse();
});
test('forceDelete permanently removes role', function () {
$user = User::factory()->create();
grantManageAccessRights($user);
$role = Role::create(['name' => 'gone-forever', 'guard_name' => 'web']);
$role->delete();
$this->actingAs($user)
->deleteJson("/roles/{$role->id}/force")
->assertOk();
expect(Role::withTrashed()->find($role->id))->toBeNull();
});
test('forceDelete blocks when role has users assigned', function () {
$admin = User::factory()->create();
grantManageAccessRights($admin);
$role = Role::create(['name' => 'sticky', 'guard_name' => 'web']);
$victim = User::factory()->create();
$victim->assignRole($role);
$this->actingAs($admin)
->deleteJson("/roles/{$role->id}/force")
->assertStatus(422);
expect(Role::find($role->id))->not->toBeNull();
});