clusev/tests/Feature/UserFactorSemanticsTest.php

59 lines
1.9 KiB
PHP

<?php
namespace Tests\Feature;
use App\Models\User;
use App\Models\WebauthnCredential;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class UserFactorSemanticsTest extends TestCase
{
use RefreshDatabase;
private function totpUser(): User
{
return User::factory()->create(['two_factor_secret' => 'S', 'two_factor_confirmed_at' => now()]);
}
private function keyUser(): User
{
$u = User::factory()->create();
WebauthnCredential::create(['user_id' => $u->id, 'name' => 'k', 'credential_id' => 'cid', 'public_key' => '{}', 'sign_count' => 0]);
return $u->fresh();
}
public function test_has_totp_only_reflects_totp(): void
{
$this->assertTrue($this->totpUser()->hasTotp());
$this->assertFalse($this->keyUser()->hasTotp());
}
public function test_has_two_factor_enabled_is_either_factor(): void
{
$this->assertTrue($this->totpUser()->hasTwoFactorEnabled());
$this->assertTrue($this->keyUser()->hasTwoFactorEnabled());
$this->assertFalse(User::factory()->create()->hasTwoFactorEnabled());
}
public function test_security_onboarded_is_password_rotation_only(): void
{
$this->assertTrue(User::factory()->create(['must_change_password' => false])->securityOnboarded());
$this->assertFalse(User::factory()->create(['must_change_password' => true])->securityOnboarded());
}
public function test_reset_if_no_factor_clears_codes_only_when_no_factor_remains(): void
{
$totp = $this->totpUser();
$totp->replaceRecoveryCodes();
$totp->resetIfNoFactor();
$this->assertTrue($totp->fresh()->hasRecoveryCodes(), 'codes kept while a factor remains');
$none = User::factory()->create();
$none->replaceRecoveryCodes();
$none->resetIfNoFactor();
$this->assertFalse($none->fresh()->hasRecoveryCodes(), 'codes cleared when no factor remains');
}
}