mirror of
https://github.com/usetrmnl/byos_laravel.git
synced 2026-01-13 15:07:49 +00:00
This commit is contained in:
parent
a88e72b75e
commit
ba3bf31bb7
29 changed files with 2379 additions and 215 deletions
|
|
@ -1,158 +1,149 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Feature\Auth;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Laravel\Socialite\Facades\Socialite;
|
||||
use Laravel\Socialite\Two\User as SocialiteUser;
|
||||
use Mockery;
|
||||
use Tests\TestCase;
|
||||
|
||||
class OidcAuthenticationTest extends TestCase
|
||||
beforeEach(function (): void {
|
||||
// Enable OIDC for testing
|
||||
Config::set('services.oidc.enabled', true);
|
||||
Config::set('services.oidc.endpoint', 'https://example.com/oidc');
|
||||
Config::set('services.oidc.client_id', 'test-client-id');
|
||||
Config::set('services.oidc.client_secret', 'test-client-secret');
|
||||
|
||||
// Mock Socialite OIDC driver to avoid any external HTTP calls
|
||||
$provider = Mockery::mock();
|
||||
$provider->shouldReceive('redirect')->andReturn(redirect('/fake-oidc-redirect'));
|
||||
|
||||
// Default Socialite user returned by callback
|
||||
$socialiteUser = mockSocialiteUser();
|
||||
$provider->shouldReceive('user')->andReturn($socialiteUser);
|
||||
|
||||
Socialite::shouldReceive('driver')
|
||||
->with('oidc')
|
||||
->andReturn($provider);
|
||||
});
|
||||
|
||||
afterEach(function (): void {
|
||||
Mockery::close();
|
||||
});
|
||||
|
||||
it('oidc redirect works when enabled', function (): void {
|
||||
$response = $this->get(route('auth.oidc.redirect'));
|
||||
|
||||
// Since we're using a mock OIDC provider, this will likely fail
|
||||
// but we can check that the route exists and is accessible
|
||||
expect($response->getStatusCode())->not->toBe(404);
|
||||
});
|
||||
|
||||
it('oidc redirect fails when disabled', function (): void {
|
||||
Config::set('services.oidc.enabled', false);
|
||||
|
||||
$response = $this->get(route('auth.oidc.redirect'));
|
||||
|
||||
$response->assertRedirect(route('login'));
|
||||
$response->assertSessionHasErrors(['oidc' => 'OIDC authentication is not enabled.']);
|
||||
});
|
||||
|
||||
it('oidc callback creates new user (placeholder)', function (): void {
|
||||
mockSocialiteUser();
|
||||
|
||||
$this->get(route('auth.oidc.callback'));
|
||||
|
||||
// We expect to be redirected to dashboard after successful authentication
|
||||
// In a real test, this would be mocked properly
|
||||
expect(true)->toBeTrue(); // Placeholder assertion
|
||||
});
|
||||
|
||||
it('oidc callback updates existing user by oidc_sub (placeholder)', function (): void {
|
||||
// Create a user with OIDC sub
|
||||
User::factory()->create([
|
||||
'oidc_sub' => 'test-sub-123',
|
||||
'name' => 'Old Name',
|
||||
'email' => 'old@example.com',
|
||||
]);
|
||||
|
||||
mockSocialiteUser([
|
||||
'id' => 'test-sub-123',
|
||||
'name' => 'Updated Name',
|
||||
'email' => 'updated@example.com',
|
||||
]);
|
||||
|
||||
// This would need proper mocking of Socialite in a real test
|
||||
expect(true)->toBeTrue(); // Placeholder assertion
|
||||
});
|
||||
|
||||
it('oidc callback links existing user by email (placeholder)', function (): void {
|
||||
// Create a user without OIDC sub but with matching email
|
||||
User::factory()->create([
|
||||
'oidc_sub' => null,
|
||||
'email' => 'test@example.com',
|
||||
]);
|
||||
|
||||
mockSocialiteUser([
|
||||
'id' => 'test-sub-456',
|
||||
'email' => 'test@example.com',
|
||||
]);
|
||||
|
||||
// This would need proper mocking of Socialite in a real test
|
||||
expect(true)->toBeTrue(); // Placeholder assertion
|
||||
});
|
||||
|
||||
it('oidc callback fails when disabled', function (): void {
|
||||
Config::set('services.oidc.enabled', false);
|
||||
|
||||
$response = $this->get(route('auth.oidc.callback'));
|
||||
|
||||
$response->assertRedirect(route('login'));
|
||||
$response->assertSessionHasErrors(['oidc' => 'OIDC authentication is not enabled.']);
|
||||
});
|
||||
|
||||
it('login view shows oidc button when enabled', function (): void {
|
||||
$response = $this->get(route('login'));
|
||||
|
||||
$response->assertStatus(200);
|
||||
$response->assertSee('Continue with OIDC');
|
||||
$response->assertSee('Or');
|
||||
});
|
||||
|
||||
it('login view hides oidc button when disabled', function (): void {
|
||||
Config::set('services.oidc.enabled', false);
|
||||
|
||||
$response = $this->get(route('login'));
|
||||
|
||||
$response->assertStatus(200);
|
||||
$response->assertDontSee('Continue with OIDC');
|
||||
});
|
||||
|
||||
it('user model has oidc_sub fillable', function (): void {
|
||||
$user = new User();
|
||||
|
||||
expect($user->getFillable())->toContain('oidc_sub');
|
||||
});
|
||||
|
||||
/**
|
||||
* Mock a Socialite user for testing.
|
||||
*
|
||||
* @param array<string, mixed> $userData
|
||||
*/
|
||||
function mockSocialiteUser(array $userData = []): SocialiteUser
|
||||
{
|
||||
use RefreshDatabase;
|
||||
$defaultData = [
|
||||
'id' => 'test-sub-123',
|
||||
'name' => 'Test User',
|
||||
'email' => 'test@example.com',
|
||||
'avatar' => null,
|
||||
];
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
// Enable OIDC for testing
|
||||
Config::set('services.oidc.enabled', true);
|
||||
Config::set('services.oidc.endpoint', 'https://example.com/oidc');
|
||||
Config::set('services.oidc.client_id', 'test-client-id');
|
||||
Config::set('services.oidc.client_secret', 'test-client-secret');
|
||||
}
|
||||
$userData = array_merge($defaultData, $userData);
|
||||
|
||||
public function test_oidc_redirect_works_when_enabled()
|
||||
{
|
||||
$response = $this->get(route('auth.oidc.redirect'));
|
||||
/** @var SocialiteUser $socialiteUser */
|
||||
$socialiteUser = Mockery::mock(SocialiteUser::class);
|
||||
$socialiteUser->shouldReceive('getId')->andReturn($userData['id']);
|
||||
$socialiteUser->shouldReceive('getName')->andReturn($userData['name']);
|
||||
$socialiteUser->shouldReceive('getEmail')->andReturn($userData['email']);
|
||||
$socialiteUser->shouldReceive('getAvatar')->andReturn($userData['avatar']);
|
||||
|
||||
// Since we're using a mock OIDC provider, this will likely fail
|
||||
// but we can check that the route exists and is accessible
|
||||
$this->assertNotEquals(404, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function test_oidc_redirect_fails_when_disabled()
|
||||
{
|
||||
Config::set('services.oidc.enabled', false);
|
||||
|
||||
$response = $this->get(route('auth.oidc.redirect'));
|
||||
|
||||
$response->assertRedirect(route('login'));
|
||||
$response->assertSessionHasErrors(['oidc' => 'OIDC authentication is not enabled.']);
|
||||
}
|
||||
|
||||
public function test_oidc_callback_creates_new_user()
|
||||
{
|
||||
$mockUser = $this->mockSocialiteUser();
|
||||
|
||||
$response = $this->get(route('auth.oidc.callback'));
|
||||
|
||||
// We expect to be redirected to dashboard after successful authentication
|
||||
// In a real test, this would be mocked properly
|
||||
$this->assertTrue(true); // Placeholder assertion
|
||||
}
|
||||
|
||||
public function test_oidc_callback_updates_existing_user_by_oidc_sub()
|
||||
{
|
||||
// Create a user with OIDC sub
|
||||
$user = User::factory()->create([
|
||||
'oidc_sub' => 'test-sub-123',
|
||||
'name' => 'Old Name',
|
||||
'email' => 'old@example.com',
|
||||
]);
|
||||
|
||||
$mockUser = $this->mockSocialiteUser([
|
||||
'id' => 'test-sub-123',
|
||||
'name' => 'Updated Name',
|
||||
'email' => 'updated@example.com',
|
||||
]);
|
||||
|
||||
// This would need proper mocking of Socialite in a real test
|
||||
$this->assertTrue(true); // Placeholder assertion
|
||||
}
|
||||
|
||||
public function test_oidc_callback_links_existing_user_by_email()
|
||||
{
|
||||
// Create a user without OIDC sub but with matching email
|
||||
$user = User::factory()->create([
|
||||
'oidc_sub' => null,
|
||||
'email' => 'test@example.com',
|
||||
]);
|
||||
|
||||
$mockUser = $this->mockSocialiteUser([
|
||||
'id' => 'test-sub-456',
|
||||
'email' => 'test@example.com',
|
||||
]);
|
||||
|
||||
// This would need proper mocking of Socialite in a real test
|
||||
$this->assertTrue(true); // Placeholder assertion
|
||||
}
|
||||
|
||||
public function test_oidc_callback_fails_when_disabled()
|
||||
{
|
||||
Config::set('services.oidc.enabled', false);
|
||||
|
||||
$response = $this->get(route('auth.oidc.callback'));
|
||||
|
||||
$response->assertRedirect(route('login'));
|
||||
$response->assertSessionHasErrors(['oidc' => 'OIDC authentication is not enabled.']);
|
||||
}
|
||||
|
||||
public function test_login_view_shows_oidc_button_when_enabled()
|
||||
{
|
||||
$response = $this->get(route('login'));
|
||||
|
||||
$response->assertStatus(200);
|
||||
$response->assertSee('Continue with OIDC');
|
||||
$response->assertSee('Or');
|
||||
}
|
||||
|
||||
public function test_login_view_hides_oidc_button_when_disabled()
|
||||
{
|
||||
Config::set('services.oidc.enabled', false);
|
||||
|
||||
$response = $this->get(route('login'));
|
||||
|
||||
$response->assertStatus(200);
|
||||
$response->assertDontSee('Continue with OIDC');
|
||||
}
|
||||
|
||||
public function test_user_model_has_oidc_sub_fillable()
|
||||
{
|
||||
$user = new User();
|
||||
|
||||
$this->assertContains('oidc_sub', $user->getFillable());
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock a Socialite user for testing.
|
||||
*/
|
||||
protected function mockSocialiteUser(array $userData = [])
|
||||
{
|
||||
$defaultData = [
|
||||
'id' => 'test-sub-123',
|
||||
'name' => 'Test User',
|
||||
'email' => 'test@example.com',
|
||||
'avatar' => null,
|
||||
];
|
||||
|
||||
$userData = array_merge($defaultData, $userData);
|
||||
|
||||
$socialiteUser = Mockery::mock(SocialiteUser::class);
|
||||
$socialiteUser->shouldReceive('getId')->andReturn($userData['id']);
|
||||
$socialiteUser->shouldReceive('getName')->andReturn($userData['name']);
|
||||
$socialiteUser->shouldReceive('getEmail')->andReturn($userData['email']);
|
||||
$socialiteUser->shouldReceive('getAvatar')->andReturn($userData['avatar']);
|
||||
|
||||
return $socialiteUser;
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
Mockery::close();
|
||||
parent::tearDown();
|
||||
}
|
||||
}
|
||||
return $socialiteUser;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue