authentikate/tests/Feature/ConsentScreenTest.php
Javier Feliz 81728c1623
Some checks failed
tests / ci (push) Waiting to run
linter / quality (push) Has been cancelled
Bring up test coverage
2025-08-02 17:00:25 -04:00

243 lines
7.9 KiB
PHP

<?php
use App\Livewire\ConsentScreen;
use App\Models\Application;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
uses(RefreshDatabase::class);
it('mounts correctly with session data', function () {
$user = User::factory()->create();
$app = Application::factory()->create(['name' => 'Test Application']);
$this->actingAs($user);
// Set up session data
session(['app_id' => $app->id, 'redirect_on_confirm' => 'https://example.com/callback']);
$component = Livewire::test(ConsentScreen::class);
expect($component->get('client')->id)->toBe($app->id);
expect($component->get('client')->name)->toBe('Test Application');
expect($component->get('redirectUrl'))->toBe('https://example.com/callback');
});
it('displays client application name', function () {
$user = User::factory()->create(['name' => 'John Doe']);
$app = Application::factory()->create(['name' => 'My OAuth App']);
$this->actingAs($user);
session(['app_id' => $app->id, 'redirect_on_confirm' => 'https://example.com/callback']);
$component = Livewire::test(ConsentScreen::class);
$component->assertSeeText('My OAuth App')
->assertSeeText('John Doe')
->assertSeeText('about to log into')
->assertSeeText('Logging in as:');
});
it('approves and redirects to redirect URL', function () {
$user = User::factory()->create();
$app = Application::factory()->create();
$this->actingAs($user);
session(['app_id' => $app->id, 'redirect_on_confirm' => 'https://example.com/callback?code=123']);
Livewire::test(ConsentScreen::class)
->call('approve')
->assertRedirect('https://example.com/callback?code=123');
// Check that session data is cleared
expect(session('app_id'))->toBeNull();
expect(session('redirect_on_confirm'))->toBeNull();
});
it('denies and redirects to dashboard', function () {
$user = User::factory()->create();
$app = Application::factory()->create();
$this->actingAs($user);
session(['app_id' => $app->id, 'redirect_on_confirm' => 'https://example.com/callback']);
Livewire::test(ConsentScreen::class)
->call('deny')
->assertRedirect(route('dashboard'));
});
it('clears session data on approval', function () {
$user = User::factory()->create();
$app = Application::factory()->create();
$this->actingAs($user);
session(['app_id' => $app->id, 'redirect_on_confirm' => 'https://example.com/callback']);
// Verify session data exists before approval
expect(session('app_id'))->toBe($app->id);
expect(session('redirect_on_confirm'))->toBe('https://example.com/callback');
Livewire::test(ConsentScreen::class)
->call('approve');
// Verify session data is cleared after approval
expect(session('app_id'))->toBeNull();
expect(session('redirect_on_confirm'))->toBeNull();
});
it('handles different redirect URL formats', function () {
$user = User::factory()->create();
$app = Application::factory()->create();
$this->actingAs($user);
$redirectUrls = [
'https://example.com/oauth/callback',
'http://localhost:3000/auth/callback?state=xyz',
'https://app.example.com:8080/callback?code=abc&state=def'
];
foreach ($redirectUrls as $redirectUrl) {
session(['app_id' => $app->id, 'redirect_on_confirm' => $redirectUrl]);
Livewire::test(ConsentScreen::class)
->call('approve')
->assertRedirect($redirectUrl);
// Reset session for next iteration
session()->flush();
}
});
it('can be rendered with valid session data', function () {
$user = User::factory()->create();
$app = Application::factory()->create();
$this->actingAs($user);
session(['app_id' => $app->id, 'redirect_on_confirm' => 'https://example.com/callback']);
$component = Livewire::test(ConsentScreen::class);
$component->assertStatus(200);
});
it('requires redirect URL in session', function () {
$user = User::factory()->create();
$app = Application::factory()->create();
$this->actingAs($user);
// Set only app_id, missing redirect_on_confirm
session(['app_id' => $app->id]);
// This should fail because redirectUrl is typed as string and session('redirect_on_confirm') returns null
expect(fn() => Livewire::test(ConsentScreen::class))
->toThrow(\Illuminate\View\ViewException::class);
});
it('displays confirm and cancel buttons', function () {
$user = User::factory()->create();
$app = Application::factory()->create();
$this->actingAs($user);
session(['app_id' => $app->id, 'redirect_on_confirm' => 'https://example.com/callback']);
$component = Livewire::test(ConsentScreen::class);
$component->assertSeeText('Confirm')
->assertSeeText('Cancel');
});
it('shows user name in consent message', function () {
$user = User::factory()->create(['name' => 'Alice Smith']);
$app = Application::factory()->create();
$this->actingAs($user);
session(['app_id' => $app->id, 'redirect_on_confirm' => 'https://example.com/callback']);
$component = Livewire::test(ConsentScreen::class);
$component->assertSeeText('Alice Smith');
});
it('requires session data to mount', function () {
$user = User::factory()->create();
$this->actingAs($user);
// No session data set - should fail due to strict typing
expect(fn() => Livewire::test(ConsentScreen::class))
->toThrow(\Illuminate\View\ViewException::class);
});
it('handles application with special characters in name', function () {
$user = User::factory()->create();
$app = Application::factory()->create(['name' => "O'Reilly's OAuth & API Service!"]);
$this->actingAs($user);
session(['app_id' => $app->id, 'redirect_on_confirm' => 'https://example.com/callback']);
$component = Livewire::test(ConsentScreen::class);
$component->assertSeeText("O'Reilly's OAuth & API Service!");
});
it('preserves URL parameters in redirect URL', function () {
$user = User::factory()->create();
$app = Application::factory()->create();
$this->actingAs($user);
$complexRedirectUrl = 'https://example.com/callback?code=xyz&state=abc123&scope=read%20write';
session(['app_id' => $app->id, 'redirect_on_confirm' => $complexRedirectUrl]);
Livewire::test(ConsentScreen::class)
->call('approve')
->assertRedirect($complexRedirectUrl);
});
it('does not redirect when denying without clearing app session data', function () {
$user = User::factory()->create();
$app = Application::factory()->create();
$this->actingAs($user);
session(['app_id' => $app->id, 'redirect_on_confirm' => 'https://example.com/callback']);
Livewire::test(ConsentScreen::class)
->call('deny')
->assertRedirect(route('dashboard'));
// Note: deny() doesn't clear session data, only approve() does
// This might be intentional behavior for security reasons
});
it('works with different user types', function () {
$adminUser = User::factory()->create(['is_admin' => true, 'name' => 'Admin User']);
$regularUser = User::factory()->create(['is_admin' => false, 'name' => 'Regular User']);
$app = Application::factory()->create(['name' => 'Test App']);
foreach ([$adminUser, $regularUser] as $user) {
$this->actingAs($user);
session(['app_id' => $app->id, 'redirect_on_confirm' => 'https://example.com/callback']);
$component = Livewire::test(ConsentScreen::class);
expect($component->get('client')->id)->toBe($app->id);
$component->assertSeeText($user->name);
// Clean up for next iteration
auth()->logout();
session()->flush();
}
});