@foreach ($enabled_oauth_providers as $provider_setting)
@endforeach
diff --git a/resources/views/livewire/settings-oauth.blade.php b/resources/views/livewire/settings-oauth.blade.php
index 4a394a0b9d..822c035b31 100644
--- a/resources/views/livewire/settings-oauth.blade.php
+++ b/resources/views/livewire/settings-oauth.blade.php
@@ -55,14 +55,39 @@
-
-
-
+ @if ($provider === 'oidc')
+
+
+
+
+
+
+
+
+
+ @else
+
+
+
+ @endif
@if ($provider === 'azure')
@endif
- @if ($provider === 'oidc')
-
-
-
-
- @endif
diff --git a/tests/Feature/LoginPageBrandingTest.php b/tests/Feature/LoginPageBrandingTest.php
index 5d60290abd..ffe7da67ce 100644
--- a/tests/Feature/LoginPageBrandingTest.php
+++ b/tests/Feature/LoginPageBrandingTest.php
@@ -37,6 +37,28 @@ test('auth pages use the Coollabs purple background glow', function () {
->not->toMatch('/\.auth-shell\s*\{[^}]*color-mix\(in oklab, var\(--color-accent\) 9%, transparent\)/s');
});
+test('external login providers are centered and full width', function () {
+ $login = file_get_contents(resource_path('views/auth/login.blade.php'));
+
+ expect($login)
+ ->toContain('class="flex flex-col gap-2"')
+ ->toContain('class="w-full justify-center"')
+ ->not->toContain('sm:w-[calc(50%-0.25rem)]');
+});
+
+test('external login providers display their icons except oidc', function () {
+ $login = file_get_contents(resource_path('views/auth/login.blade.php'));
+
+ expect($login)
+ ->toContain("@if (\$provider_setting->provider !== 'oidc')")
+ ->toContain("asset('svgs/'.\$provider_setting->provider.'.svg')")
+ ->toContain('class="size-5 shrink-0 dark:invert"');
+
+ foreach (['authentik', 'azure', 'bitbucket', 'clerk', 'discord', 'github', 'gitlab', 'google', 'infomaniak', 'zitadel'] as $provider) {
+ expect(public_path("svgs/{$provider}.svg"))->toBeFile();
+ }
+});
+
test('error pages use the Coollabs purple background glow', function () {
$styles = file_get_contents(resource_path('css/app.css'));
diff --git a/tests/Feature/SettingsOauthTest.php b/tests/Feature/SettingsOauthTest.php
index 6849b3d79a..95ea47e948 100644
--- a/tests/Feature/SettingsOauthTest.php
+++ b/tests/Feature/SettingsOauthTest.php
@@ -94,6 +94,27 @@ it('shows oidc fields with a naked okta issuer url example', function () {
->assertDontSee('/oauth2/default', false);
});
+it('groups oidc fields in the expected desktop order', function () {
+ $view = file_get_contents(resource_path('views/livewire/settings-oauth.blade.php'));
+ $fields = [
+ 'redirect_uri',
+ 'base_url',
+ 'client_id',
+ 'client_secret',
+ 'scopes',
+ 'clock_skew_seconds',
+ 'custom_label',
+ ];
+ $positions = array_map(
+ fn (string $field): int|false => strpos($view, "id=\"oauth_settings_map.{{ \$provider }}.$field\""),
+ $fields,
+ );
+
+ expect($positions)->not->toContain(false)
+ ->and($positions)->toBe(collect($positions)->sort()->values()->all())
+ ->and($view)->toContain('
');
+});
+
it('shows provider enable controls as settings section actions', function () {
actingAsInstanceAdmin();
diff --git a/tests/Feature/UserSeederTest.php b/tests/Feature/UserSeederTest.php
new file mode 100644
index 0000000000..d8ccf86510
--- /dev/null
+++ b/tests/Feature/UserSeederTest.php
@@ -0,0 +1,16 @@
+seed(UserSeeder::class);
+
+ $user = User::factory()->create();
+
+ expect(User::query()->orderBy('id')->pluck('id')->all())->toBe([0, 1, 2, 3])
+ ->and($user->id)->toBe(3);
+});