actingAs($this->operationalUser(), 'sanctum'); UserRole::factory()->count(2)->create(); $this->getJson('/api/user-roles') ->assertOk() ->assertJsonStructure(['message', 'data' => [['id', 'name', 'description']]]); } public function test_show_returns_a_single_role(): void { $this->actingAs($this->operationalUser(), 'sanctum'); $role = UserRole::factory()->create(); $this->getJson("/api/user-roles/{$role->id}") ->assertOk() ->assertJsonPath('data.id', $role->id) ->assertJsonPath('data.name', $role->name); } public function test_usage_flags_system_role_as_locked(): void { $this->actingAs($this->operationalUser(), 'sanctum'); $role = UserRole::create(['name' => UserRole::SUPERVISOR]); $this->getJson("/api/user-roles/{$role->id}/usage") ->assertOk() ->assertJsonPath('in_use', true); } public function test_usage_flags_free_custom_role_as_unlocked(): void { $this->actingAs($this->operationalUser(), 'sanctum'); $role = UserRole::factory()->create(); $this->getJson("/api/user-roles/{$role->id}/usage") ->assertOk() ->assertJsonPath('in_use', false); } // --- Scrittura (tier.admin) --------------------------------------------- public function test_admin_can_create_a_role(): void { $this->actingAs($this->adminUser(), 'sanctum'); $this->postJson('/api/user-roles', ['name' => 'Editor', 'description' => 'Edits stuff']) ->assertCreated() ->assertJsonPath('data.name', 'Editor'); $this->assertDatabaseHas('user_roles', ['name' => 'Editor']); } public function test_create_requires_a_name(): void { $this->actingAs($this->adminUser(), 'sanctum'); $this->postJson('/api/user-roles', ['description' => 'no name']) ->assertUnprocessable() ->assertJsonValidationErrors('name'); } public function test_create_rejects_a_duplicate_name(): void { $this->actingAs($this->adminUser(), 'sanctum'); UserRole::factory()->create(['name' => 'Editor']); $this->postJson('/api/user-roles', ['name' => 'Editor']) ->assertUnprocessable() ->assertJsonValidationErrors('name'); } public function test_admin_can_update_a_role(): void { $this->actingAs($this->adminUser(), 'sanctum'); $role = UserRole::factory()->create(['name' => 'Old']); $this->putJson("/api/user-roles/{$role->id}", ['name' => 'New']) ->assertOk() ->assertJsonPath('data.name', 'New'); $this->assertDatabaseHas('user_roles', ['id' => $role->id, 'name' => 'New']); } public function test_update_can_keep_the_same_name(): void { $this->actingAs($this->adminUser(), 'sanctum'); $role = UserRole::factory()->create(['name' => 'Stable']); $this->putJson("/api/user-roles/{$role->id}", ['name' => 'Stable']) ->assertOk(); } public function test_update_rejects_a_name_taken_by_another_role(): void { $this->actingAs($this->adminUser(), 'sanctum'); UserRole::factory()->create(['name' => 'Taken']); $role = UserRole::factory()->create(['name' => 'Mine']); $this->putJson("/api/user-roles/{$role->id}", ['name' => 'Taken']) ->assertUnprocessable() ->assertJsonValidationErrors('name'); } public function test_cannot_delete_a_system_role(): void { $this->actingAs($this->adminUser(), 'sanctum'); $role = UserRole::create(['name' => UserRole::GUEST]); $this->deleteJson("/api/user-roles/{$role->id}") ->assertStatus(409) ->assertJsonPath('in_use', true); $this->assertDatabaseHas('user_roles', ['id' => $role->id]); } public function test_cannot_delete_a_role_in_use(): void { $this->actingAs($this->adminUser(), 'sanctum'); $role = UserRole::factory()->create(['name' => 'Busy']); $this->operationalUser(['role_id' => $role->id]); $this->deleteJson("/api/user-roles/{$role->id}") ->assertStatus(409) ->assertJsonPath('in_use', true); $this->assertDatabaseHas('user_roles', ['id' => $role->id]); } public function test_admin_can_delete_a_free_custom_role(): void { $this->actingAs($this->adminUser(), 'sanctum'); $role = UserRole::factory()->create(['name' => 'Disposable']); $this->deleteJson("/api/user-roles/{$role->id}")->assertOk(); $this->assertDatabaseMissing('user_roles', ['id' => $role->id]); } // --- Gating --------------------------------------------------------------- public function test_non_admin_cannot_write(): void { $this->actingAs($this->operationalUser(), 'sanctum'); $this->postJson('/api/user-roles', ['name' => 'Nope'])->assertForbidden(); } }