assertRedirect(route('login')); }); it('returns 403 when user has no permission to view roles', function () { actingAs(createUnauthorizedUser()) ->get(route('system.role.index')) ->assertStatus(403); }); }); describe('Role Module - Authorized Actions', function () { beforeEach(function () { $user = createAuthorizedUser([ 'View:Role', 'Create:Role', 'Edit:Role', 'Delete:Role', 'DeleteAny:Role', ]); actingAs($user); }); it('can access role index page', function () { get(route('system.role.index')) ->assertOk() ->assertInertia(fn ($page) => $page ->component('admin/system/role/index') ->has('roles') ); }); it('can access role create page', function () { get(route('system.role.create')) ->assertOk() ->assertInertia(fn ($page) => $page ->component('admin/system/role/create') ->has('permissions') ); }); it('can store a new role with permissions', function () { $permissions = [ Permission::create(['name' => 'TestPermission1', 'guard_name' => 'web'])->id, Permission::create(['name' => 'TestPermission2', 'guard_name' => 'web'])->id, ]; $data = [ 'name' => 'New Role', 'guard_name' => 'web', 'permissions' => $permissions, ]; postJson(route('system.role.store'), $data) ->assertRedirect(route('system.role.index')) ->assertSessionHas('success'); assertDatabaseHas('roles', [ 'name' => 'New Role', ]); $role = Role::findByName('New Role'); expect($role->permissions)->toHaveCount(2); }); it('validates role creation', function () { postJson(route('system.role.store'), []) ->assertStatus(422) ->assertJsonValidationErrors(['name', 'guard_name']); }); it('can access role edit page', function () { $role = Role::create(['name' => 'Test Role', 'guard_name' => 'web']); get(route('system.role.edit', $role)) ->assertOk() ->assertInertia(fn ($page) => $page ->component('admin/system/role/edit') ->has('role') ->has('permissions') ); }); it('can update a role and sync permissions', function () { $role = Role::create(['name' => 'Old Role', 'guard_name' => 'web']); $permission = Permission::create(['name' => 'TestPermission3', 'guard_name' => 'web']); $newData = [ 'name' => 'Updated Role', 'guard_name' => 'web', 'permissions' => [$permission->id], ]; putJson(route('system.role.update', $role), $newData) ->assertRedirect(route('system.role.index')) ->assertSessionHas('success'); assertDatabaseHas('roles', [ 'id' => $role->id, 'name' => 'Updated Role', ]); expect($role->fresh()->permissions)->toHaveCount(1); expect($role->fresh()->permissions->first()->name)->toBe('TestPermission3'); }); it('can delete a role', function () { $role = Role::create(['name' => 'Delete Me', 'guard_name' => 'web']); deleteJson(route('system.role.destroy', $role)) ->assertRedirect() ->assertSessionHas('success'); // Spatie Role usually doesn't use soft deletes unless configured, // so we check if it's missing from DB. assertDatabaseMissing('roles', ['id' => $role->id]); }); it('can delete roles in bulk', function () { $roles = [ Role::create(['name' => 'Bulk 1', 'guard_name' => 'web'])->id, Role::create(['name' => 'Bulk 2', 'guard_name' => 'web'])->id, ]; postJson(route('system.role.bulk-destroy'), ['ids' => $roles]) ->assertRedirect() ->assertSessionHas('success'); foreach ($roles as $id) { assertDatabaseMissing('roles', ['id' => $id]); } }); }); describe('Role Module - Unauthorized Actions', function () { beforeEach(function () { actingAs(createUnauthorizedUser()); }); it('cannot store a role without permission', function () { postJson(route('system.role.store'), ['name' => 'Unauthorized']) ->assertStatus(403); }); it('cannot update a role without permission', function () { $role = Role::create(['name' => 'Unauthorized Role', 'guard_name' => 'web']); putJson(route('system.role.update', $role), ['name' => 'Unauthorized']) ->assertStatus(403); }); it('cannot delete a role without permission', function () { $role = Role::create(['name' => 'Unauthorized Role', 'guard_name' => 'web']); deleteJson(route('system.role.destroy', $role)) ->assertStatus(403); }); });