create(['name' => 'Op', 'email' => 'op@example.com', 'roles' => ['operator']]); $this->actingAs($operator)->get('/admin')->assertForbidden(); }); test('admin creates an api key and sees the plaintext token exactly once', function () { $admin = adminUser(); $component = Livewire::actingAs($admin)->test(ApiKeys::class) ->call('openForm') ->set('form.name', 'Monitoring integracja') ->set('form.description', 'Tworzy zgłoszenia z systemu monitoringu') ->set('form.abilities', ['tickets:read', 'tickets:write']) ->call('submit') ->assertOk(); $client = ApiClient::query()->where('name', 'Monitoring integracja')->firstOrFail(); expect($client->created_by)->toBe($admin->id); expect($client->tokens()->count())->toBe(1); expect($client->tokens()->first()->abilities)->toBe(['tickets:read', 'tickets:write']); $component->assertSet('newTokenPlaintext', fn ($value) => is_string($value) && str_contains($value, '|')); // Re-rendering (e.g. a page refresh) must not resurrect the plaintext secret. $fresh = Livewire::actingAs($admin)->test(ApiKeys::class); $fresh->assertSet('newTokenPlaintext', null); }); test('creating a key requires a name and at least one ability', function () { $admin = adminUser(); Livewire::actingAs($admin)->test(ApiKeys::class) ->call('openForm') ->set('form.name', '') ->set('form.abilities', []) ->call('submit') ->assertHasErrors(['form.name', 'form.abilities']); }); test('admin revokes a key and its token stops working', function () { $admin = adminUser(); $apiClient = ApiClient::factory()->create(); $token = $apiClient->createToken('test', ['tickets:read']); $plaintext = $token->plainTextToken; Livewire::actingAs($admin)->test(ApiKeys::class) ->call('revoke', $apiClient->id) ->assertOk(); $apiClient->refresh(); expect($apiClient->isRevoked())->toBeTrue(); expect($apiClient->tokens()->count())->toBe(0); }); test('admin regenerates a key, keeping its abilities but issuing a new token', function () { $admin = adminUser(); $apiClient = ApiClient::factory()->create(); $oldToken = $apiClient->createToken('test', ['tickets:read', 'users:read']); $oldTokenId = $oldToken->accessToken->id; Livewire::actingAs($admin)->test(ApiKeys::class) ->call('regenerate', $apiClient->id) ->assertOk(); $apiClient->refresh(); expect($apiClient->isRevoked())->toBeFalse(); expect($apiClient->tokens()->count())->toBe(1); expect($apiClient->tokens()->first()->abilities)->toBe(['tickets:read', 'users:read']); expect($apiClient->tokens()->first()->id)->not->toBe($oldTokenId); });