artisan('app:generate-keys') ->expectsOutput('Generating RSA key pair...') ->expectsOutput('✅ Keys generated:') ->expectsOutput("- Private: $privatePath") ->expectsOutput("- Public : $publicPath") ->assertExitCode(0); // Verify files were created expect(File::exists($privatePath))->toBe(true); expect(File::exists($publicPath))->toBe(true); // Verify file permissions expect(substr(sprintf('%o', fileperms($privatePath)), -3))->toBe('600'); expect(substr(sprintf('%o', fileperms($publicPath)), -3))->toBe('644'); // Verify key content is valid $privateKeyContent = File::get($privatePath); $publicKeyContent = File::get($publicPath); expect($privateKeyContent)->toContain('-----BEGIN PRIVATE KEY-----'); expect($privateKeyContent)->toContain('-----END PRIVATE KEY-----'); expect($publicKeyContent)->toContain('-----BEGIN PUBLIC KEY-----'); expect($publicKeyContent)->toContain('-----END PUBLIC KEY-----'); // Verify the keys are actually valid RSA keys $privateKey = openssl_pkey_get_private($privateKeyContent); $publicKey = openssl_pkey_get_public($publicKeyContent); expect($privateKey)->not()->toBe(false); expect($publicKey)->not()->toBe(false); }); it('prevents overwriting existing keys', function () { $keyDir = storage_path('testing/oauth'); $privatePath = "$keyDir/private.pem"; $publicPath = "$keyDir/public.pem"; // Create directory and dummy files File::makeDirectory($keyDir, 0700, true); File::put($privatePath, 'dummy private key'); File::put($publicPath, 'dummy public key'); $this->artisan('app:generate-keys') ->expectsOutput('Keys already exist. Aborting.') ->assertExitCode(0); // Verify original files are unchanged expect(File::get($privatePath))->toBe('dummy private key'); expect(File::get($publicPath))->toBe('dummy public key'); }); it('creates oauth directory if it does not exist', function () { $keyDir = storage_path('testing/oauth'); // Ensure directory doesn't exist expect(File::exists($keyDir))->toBe(false); $this->artisan('app:generate-keys') ->assertExitCode(0); // Verify directory was created with correct permissions expect(File::exists($keyDir))->toBe(true); expect(substr(sprintf('%o', fileperms($keyDir)), -3))->toBe('700'); }); it('generates different keys on multiple runs', function () { // First generation $this->artisan('app:generate-keys')->assertExitCode(0); $keyDir = storage_path('testing/oauth'); $privatePath = "$keyDir/private.pem"; $publicPath = "$keyDir/public.pem"; $firstPrivateKey = File::get($privatePath); $firstPublicKey = File::get($publicPath); // Clean up and generate again File::deleteDirectory($keyDir); $this->artisan('app:generate-keys')->assertExitCode(0); $secondPrivateKey = File::get($privatePath); $secondPublicKey = File::get($publicPath); // Keys should be different expect($firstPrivateKey)->not()->toBe($secondPrivateKey); expect($firstPublicKey)->not()->toBe($secondPublicKey); }); it('generates 2048-bit RSA keys', function () { $this->artisan('app:generate-keys')->assertExitCode(0); $keyDir = storage_path('testing/oauth'); $privatePath = "$keyDir/private.pem"; $privateKeyContent = File::get($privatePath); $privateKey = openssl_pkey_get_private($privateKeyContent); $details = openssl_pkey_get_details($privateKey); expect($details['bits'])->toBe(2048); expect($details['type'])->toBe(OPENSSL_KEYTYPE_RSA); }); it('supports custom path option', function () { $customDir = storage_path('testing/custom-oauth'); $privatePath = "$customDir/private.pem"; $publicPath = "$customDir/public.pem"; $this->artisan("app:generate-keys --path={$customDir}") ->expectsOutput('Generating RSA key pair...') ->expectsOutput('✅ Keys generated:') ->expectsOutput("- Private: $privatePath") ->expectsOutput("- Public : $publicPath") ->assertExitCode(0); // Verify files were created in custom directory expect(File::exists($privatePath))->toBe(true); expect(File::exists($publicPath))->toBe(true); // Clean up custom directory File::deleteDirectory($customDir); }); });