192 lines
6.7 KiB
PHP
192 lines
6.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Feature\Console\Commands;
|
|
|
|
use Infra\Database\Models\ApiClient;
|
|
use Presentation\Console\Commands\RegenerateClientSecretCommand;
|
|
use Ramsey\Uuid\Uuid;
|
|
use Symfony\Component\Console\Tester\CommandCompletionTester;
|
|
|
|
covers(RegenerateClientSecretCommand::class);
|
|
|
|
describe('RegenerateClientSecretCommand', function (): void {
|
|
it('errors when an invalid identifier is provided', function (): void {
|
|
// GIVEN
|
|
/** @var \Tests\TestCase $this */
|
|
$invalidIdentifier = 'invalid-id';
|
|
|
|
// WHEN
|
|
$this->artisan('client:regenerate-secret', ['identifier' => $invalidIdentifier])
|
|
|
|
// THEN
|
|
->expectsOutput("Invalid client identifier '{$invalidIdentifier}'. Expected a valid client identifier.")
|
|
->assertFailed();
|
|
});
|
|
|
|
it('errors when client does not exist', function (): void {
|
|
// GIVEN
|
|
/** @var \Tests\TestCase $this */
|
|
$nonExistentIdentifier = 'arcadia_id_' . str_repeat('f', 32);
|
|
|
|
// WHEN
|
|
$this->artisan('client:regenerate-secret', ['identifier' => $nonExistentIdentifier])
|
|
|
|
// THEN
|
|
->expectsOutput("Client '{$nonExistentIdentifier}' not found.")
|
|
->assertFailed();
|
|
});
|
|
|
|
it('regenerates secret when confirmed with argument provided', function (): void {
|
|
// GIVEN
|
|
/** @var \Tests\TestCase $this */
|
|
$identifier = 'arcadia_id_' . str_repeat('a', 32);
|
|
$oldSecret = 'arcadia_sec_' . str_repeat('1', 86);
|
|
|
|
$client = ApiClient::query()->create([
|
|
'id' => (string) Uuid::uuid7(),
|
|
'name' => 'Production Gateway',
|
|
'slug' => 'production-gateway',
|
|
'identifier' => $identifier,
|
|
'secret' => $oldSecret,
|
|
'is_active' => true,
|
|
]);
|
|
|
|
// WHEN
|
|
$this->artisan('client:regenerate-secret', ['identifier' => $identifier])
|
|
|
|
// THEN
|
|
->expectsConfirmation('Do you want to proceed?', 'yes')
|
|
->expectsOutputToContain("Secret for client '{$identifier}' regenerated successfully.")
|
|
->expectsOutputToContain('Store the new secret securely')
|
|
->assertSuccessful();
|
|
|
|
$client->refresh();
|
|
expect($client->secret->value)->not->toBe($oldSecret)
|
|
->and((string) $client->secret->value)->toStartWith('arcadia_sec_');
|
|
});
|
|
|
|
it('aborts and keeps old secret when confirmation is declined', function (): void {
|
|
// GIVEN
|
|
/** @var \Tests\TestCase $this */
|
|
$identifier = 'arcadia_id_' . str_repeat('b', 32);
|
|
$oldSecret = 'arcadia_sec_' . str_repeat('2', 86);
|
|
|
|
$client = ApiClient::query()->create([
|
|
'id' => (string) Uuid::uuid7(),
|
|
'name' => 'Staging Gateway',
|
|
'slug' => 'staging-gateway',
|
|
'identifier' => $identifier,
|
|
'secret' => $oldSecret,
|
|
'is_active' => true,
|
|
]);
|
|
|
|
// WHEN
|
|
$this->artisan('client:regenerate-secret', ['identifier' => $identifier])
|
|
|
|
// THEN
|
|
->expectsConfirmation('Do you want to proceed?', 'no')
|
|
->expectsOutput('Secret regeneration cancelled.')
|
|
->assertSuccessful();
|
|
|
|
$client->refresh();
|
|
expect($client->secret->value)->toBe($oldSecret);
|
|
});
|
|
|
|
it('interactively prompts to select client when no argument is provided', function (): void {
|
|
// GIVEN
|
|
/** @var \Tests\TestCase $this */
|
|
ApiClient::query()->delete();
|
|
|
|
$identifier1 = 'arcadia_id_' . str_repeat('c', 32);
|
|
$identifier2 = 'arcadia_id_' . str_repeat('d', 32);
|
|
$oldSecret2 = 'arcadia_sec_' . str_repeat('3', 86);
|
|
|
|
ApiClient::query()->create([
|
|
'id' => (string) Uuid::uuid7(),
|
|
'name' => 'Client One',
|
|
'slug' => 'client-one',
|
|
'identifier' => $identifier1,
|
|
'secret' => 'arcadia_sec_' . str_repeat('4', 86),
|
|
'is_active' => true,
|
|
]);
|
|
|
|
$client2 = ApiClient::query()->create([
|
|
'id' => (string) Uuid::uuid7(),
|
|
'name' => 'Client Two',
|
|
'slug' => 'client-two',
|
|
'identifier' => $identifier2,
|
|
'secret' => $oldSecret2,
|
|
'is_active' => false,
|
|
]);
|
|
|
|
// WHEN
|
|
$this->artisan('client:regenerate-secret')
|
|
|
|
// THEN
|
|
->expectsChoice(
|
|
'Which client secret would you like to regenerate?',
|
|
"Client Two (Inactive) - {$identifier2}",
|
|
[
|
|
"Client One (Active) - {$identifier1}",
|
|
"Client Two (Inactive) - {$identifier2}",
|
|
],
|
|
)
|
|
->expectsConfirmation('Do you want to proceed?', 'yes')
|
|
->expectsOutputToContain("Secret for client '{$identifier2}' regenerated successfully.")
|
|
->assertSuccessful();
|
|
|
|
$client2->refresh();
|
|
expect($client2->secret->value)->not->toBe($oldSecret2);
|
|
});
|
|
|
|
it('outputs an error when no clients exist in database during interactive prompt', function (): void {
|
|
// GIVEN
|
|
/** @var \Tests\TestCase $this */
|
|
ApiClient::query()->delete();
|
|
|
|
// WHEN
|
|
$this->artisan('client:regenerate-secret')
|
|
|
|
// THEN
|
|
->expectsOutput('No clients found in the database.')
|
|
->assertFailed();
|
|
});
|
|
|
|
it('provides autocompletion suggestions for identifier', function (): void {
|
|
// GIVEN
|
|
/** @var \Tests\TestCase $this */
|
|
ApiClient::query()->delete();
|
|
|
|
ApiClient::query()->create([
|
|
'id' => (string) Uuid::uuid7(),
|
|
'name' => 'Alpha Client',
|
|
'slug' => 'alpha-client',
|
|
'identifier' => 'arcadia_id_' . str_repeat('1', 32),
|
|
'secret' => 'arcadia_sec_' . str_repeat('2', 86),
|
|
'is_active' => true,
|
|
]);
|
|
|
|
ApiClient::query()->create([
|
|
'id' => (string) Uuid::uuid7(),
|
|
'name' => 'Beta Client',
|
|
'slug' => 'beta-client',
|
|
'identifier' => 'arcadia_id_' . str_repeat('3', 32),
|
|
'secret' => 'arcadia_sec_' . str_repeat('4', 86),
|
|
'is_active' => false,
|
|
]);
|
|
|
|
/** @var RegenerateClientSecretCommand $command */
|
|
$command = app(RegenerateClientSecretCommand::class);
|
|
$tester = new CommandCompletionTester($command);
|
|
|
|
// WHEN
|
|
$suggestions = $tester->complete(['']);
|
|
|
|
// THEN
|
|
expect($suggestions)
|
|
->toContain('arcadia_id_' . str_repeat('1', 32))
|
|
->toContain('arcadia_id_' . str_repeat('3', 32));
|
|
});
|
|
});
|