artisan('db:seed'); $this->be(UserFactory::admin()->create()); }); test('permissions list', function () { $permission = Permission::factory()->create(); $this->get('permissions') ->assertSee($permission->display_name); }); test('only users with appropriate permissions can access the permissions list page', function () { $roleA = RoleFactory::create(); $roleB = RoleFactory::withPermissions('permissions.manage')->create(); $userA = UserFactory::role($roleA)->create(); $userB = UserFactory::role($roleB)->create(); $this->actingAs($userA)->get('/permissions')->assertStatus(403); $this->actingAs($userB)->get('/permissions')->assertOk(); }); test('permission list with roles', function () { $permission = Permission::factory()->create(); $role = Role::first(); $role->permissions()->attach($permission->id); $this->get('permissions') ->assertInertia(function (Assert $page) use ($permission, $role) { $page->component('permissions/Index'); $props = $page->toArray()['props']; $this->assertContains( $permission->display_name, collect($props['permissions'])->pluck('display_name')->all() ); // The granted matrix replaces the roles[{id}][] checkbox names. $this->assertContains($permission->id, $props['granted'][$role->id]); }); }); test('save role permissions', function () { $this->withoutExceptionHandling(); Event::fake([ PermissionsUpdated::class, ]); $permission = Permission::factory()->create(); $role = Role::factory()->create(); $this->post('permissions/save', [ 'roles' => [ $role->id => [$permission->id], ], ]); $this->assertSessionHasSuccess('Permissions saved successfully.'); $this->assertDatabaseHas('permission_role', [ 'role_id' => $role->id, 'permission_id' => $permission->id, ]); Event::assertDispatched(PermissionsUpdated::class); }); test('only users with appropriate permissions can save role permissions', function () { $roleA = RoleFactory::create(); $roleB = RoleFactory::withPermissions('permissions.manage')->create(); $userA = UserFactory::role($roleA)->create(); $userB = UserFactory::role($roleB)->create(); $permission = Permission::factory()->create(); $role = Role::factory()->create(); $data = [$role->id => [$permission->id]]; $this->actingAs($userA) ->post('permissions/save', ['roles' => $data]) ->assertStatus(403); $this->assertDatabaseMissing('permission_role', [ 'role_id' => $role->id, 'permission_id' => $permission->id, ]); $this->actingAs($userB) ->post('permissions/save', ['roles' => $data]); $this->assertDatabaseHas('permission_role', [ 'role_id' => $role->id, 'permission_id' => $permission->id, ]); }); test('save role permissions if no permission is selected for specific role', function () { Event::fake([ PermissionsUpdated::class, ]); $role1 = Role::factory()->create(); $permission1 = Permission::factory()->create(); $role1->permissions()->attach($permission1->id); $role2 = Role::factory()->create(); $permission2 = Permission::factory()->create(); $role2->permissions()->attach($permission2->id); $this->post('/permissions/save', [ 'roles' => [ $role1->id => [$permission1->id], ], ]); $this->assertSessionHasSuccess('Permissions saved successfully.'); $this->assertDatabaseHas('permission_role', [ 'role_id' => $role1->id, 'permission_id' => $permission1->id, ]); $this->assertDatabaseMissing('permission_role', [ 'role_id' => $role2->id, 'permission_id' => $permission2->id, ]); Event::assertDispatched(PermissionsUpdated::class); }); test('create permission', function () { $this->app->instance('middleware.disable', false); Event::fake([ Created::class, ]); $data = validPermissionParams(); $this->post('permissions', $data) ->assertRedirect('/permissions'); $this->assertSessionHasSuccess('Permission created successfully.'); $this->assertDatabaseHas('permissions', $data); Event::assertDispatched(Created::class); }); test('only users with appropriate permission can create new permissions', function () { $roleA = RoleFactory::create(); $roleB = RoleFactory::withPermissions('permissions.manage')->create(); $userA = UserFactory::role($roleA)->create(); $userB = UserFactory::role($roleB)->create(); $data = validPermissionParams(); $this->actingAs($userA) ->post('permissions', $data) ->assertStatus(403); $this->assertDatabaseMissing('permissions', $data); $this->actingAs($userB) ->post('permissions', $data) ->assertRedirect('/permissions'); $this->assertDatabaseHas('permissions', $data); }); test('permission name must have valid format', function () { $this->app->instance('middleware.disable', false); $data = validPermissionParams(); $response = $this->post('permissions', validPermissionParams(['name' => 'invalid name'])); $response->assertSessionHasErrors('name'); $this->assertDatabaseMissing('permissions', $data); $response = $this->post('permissions', validPermissionParams(['name' => 'invalid*name'])); $response->assertSessionHasErrors('name'); $this->assertDatabaseMissing('permissions', $data); }); test('update permission', function () { $this->withoutExceptionHandling(); Event::fake([ Updated::class, ]); $permission = Permission::factory()->create(); $this->get("permissions/{$permission->id}/edit") ->assertOk() ->assertSee($permission->id) ->assertSee($permission->name) ->assertSee($permission->display_name); $data = validPermissionParams(); $this->put("permissions/{$permission->id}", $data); $this->assertSessionHasSuccess('Permission updated successfully.'); $this->assertDatabaseHas('permissions', $data + ['id' => $permission->id]); Event::assertDispatched(Updated::class); }); test('only users with appropriate permission can update existing permissions', function () { $roleA = RoleFactory::create(); $roleB = RoleFactory::withPermissions('permissions.manage')->create(); $userA = UserFactory::role($roleA)->create(); $userB = UserFactory::role($roleB)->create(); $permission = Permission::factory()->create(); $data = validPermissionParams(); $this->actingAs($userA) ->put("permissions/{$permission->id}", $data) ->assertStatus(403); $this->assertEquals($permission->toArray(), $permission->fresh()->toArray()); $this->actingAs($userB) ->put("permissions/{$permission->id}", $data) ->assertRedirect('/permissions'); $permission->refresh(); $this->assertEquals($permission->name, $data['name']); $this->assertEquals($permission->display_name, $data['display_name']); $this->assertEquals($permission->description, $data['description']); }); test('removable attribute cannot be changed on update', function () { $permission = Permission::factory()->create(['removable' => false]); $data = validPermissionParams(['removable' => true]); $this->put("permissions/{$permission->id}", $data); $permission->refresh(); $this->assertEquals($permission->name, $data['name']); $this->assertEquals($permission->display_name, $data['display_name']); $this->assertEquals($permission->description, $data['description']); $this->assertFalse($permission->removable); }); test('permission name must have valid format while updating the permission', function () { $permission = Permission::factory()->create(['name' => 'foo']); $response = $this->put('permissions/'.$permission->id, validPermissionParams(['name' => 'invalid name'])); $response->assertSessionHasErrors('name'); $this->assertEquals('foo', $permission->fresh()->name); $response = $this->put('permissions/'.$permission->id, validPermissionParams(['name' => 'invalid*name'])); $response->assertSessionHasErrors('name'); $this->assertEquals('foo', $permission->fresh()->name); }); test('delete permission', function () { Event::fake([ Deleted::class, ]); $permission = Permission::factory()->create(); $this->delete(route('permissions.destroy', $permission->id)) ->assertRedirect('/permissions'); $this->assertSessionHasSuccess('Permission deleted successfully.'); $this->assertDatabaseMissing('permissions', ['id' => $permission->id]); Event::assertDispatched(Deleted::class); }); test('only users with appropriate permission can delete permissions', function () { $roleA = RoleFactory::create(); $roleB = RoleFactory::withPermissions('permissions.manage')->create(); $userA = UserFactory::role($roleA)->create(); $userB = UserFactory::role($roleB)->create(); $permission = Permission::factory()->create(); $this->actingAs($userA) ->delete("permissions/{$permission->id}") ->assertStatus(403); $this->assertNotNull($permission->fresh()); $this->actingAs($userB) ->delete("permissions/{$permission->id}") ->assertRedirect('/permissions'); $this->assertNull($permission->fresh()); }); test('non removable permissions cannot be removed', function () { $permission = Permission::factory()->create(['removable' => false]); $this->delete(route('permissions.destroy', $permission->id)) ->assertStatus(404); $this->assertNotNull($permission->fresh()); }); function validPermissionParams(array $override = []): array { return array_merge([ 'name' => 'foo_permission', 'display_name' => 'Foo Permission', 'description' => 'the description', ], $override); }