From f552338eb5ab6de1677b7deb2d4ab904dca10755 Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Thu, 30 Apr 2026 08:40:46 +0700 Subject: [PATCH] test: add RoleFactory and feature tests for role management module --- database/factories/RoleFactory.php | 27 ++++ tests/Feature/Admin/System/RoleTest.php | 177 ++++++++++++++++++++++++ 2 files changed, 204 insertions(+) create mode 100644 database/factories/RoleFactory.php create mode 100644 tests/Feature/Admin/System/RoleTest.php diff --git a/database/factories/RoleFactory.php b/database/factories/RoleFactory.php new file mode 100644 index 0000000..53477dc --- /dev/null +++ b/database/factories/RoleFactory.php @@ -0,0 +1,27 @@ + + */ +class RoleFactory extends Factory +{ + protected $model = Role::class; + + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + 'name' => fake()->unique()->jobTitle(), + 'guard_name' => 'web', + ]; + } +} diff --git a/tests/Feature/Admin/System/RoleTest.php b/tests/Feature/Admin/System/RoleTest.php new file mode 100644 index 0000000..7094775 --- /dev/null +++ b/tests/Feature/Admin/System/RoleTest.php @@ -0,0 +1,177 @@ +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); + }); +});