mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-08 00:02:15 +01:00
Added tests
This commit is contained in:
committed by
Constantin Graf
parent
c5c129b239
commit
24775d2c47
@@ -5,12 +5,9 @@ declare(strict_types=1);
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Enums\Weekday;
|
||||
use App\Mail\VerifyUpdatedEmailMail;
|
||||
use App\Models\User;
|
||||
use App\Service\TimezoneService;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ProfileInformationTest extends TestCase
|
||||
@@ -39,66 +36,4 @@ class ProfileInformationTest extends TestCase
|
||||
$user = $user->fresh();
|
||||
$this->assertEquals($user->name, $user->name);
|
||||
}
|
||||
|
||||
public function test_pending_email_verification_redirects_with_danger_banner_when_email_already_in_use(): void
|
||||
{
|
||||
// Arrange
|
||||
User::factory()->create([
|
||||
'email' => 'taken@example.com',
|
||||
'is_placeholder' => false,
|
||||
]);
|
||||
$user = User::factory()->create([
|
||||
'email' => 'current@example.com',
|
||||
'pending_email' => 'taken@example.com',
|
||||
]);
|
||||
$this->actingAs($user);
|
||||
$verificationUrl = URL::temporarySignedRoute(
|
||||
'users.verify-email-change',
|
||||
now()->addMinutes(60),
|
||||
[
|
||||
'user' => $user->getKey(),
|
||||
'email' => 'taken@example.com',
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
// Act
|
||||
$response = $this->get($verificationUrl);
|
||||
|
||||
// Assert
|
||||
$response->assertRedirect(route('dashboard'));
|
||||
$response->assertSessionHas('bannerStyle', 'danger');
|
||||
$response->assertSessionHas('bannerText', 'The email address is already in use.');
|
||||
$user = $user->fresh();
|
||||
$this->assertEquals('current@example.com', $user->email);
|
||||
$this->assertEquals('taken@example.com', $user->pending_email);
|
||||
}
|
||||
|
||||
public function test_stale_pending_email_verification_link_is_rejected(): void
|
||||
{
|
||||
// Arrange
|
||||
$user = User::factory()->create([
|
||||
'email' => 'current@example.com',
|
||||
'pending_email' => 'newer@example.com',
|
||||
]);
|
||||
$this->actingAs($user);
|
||||
$verificationUrl = URL::temporarySignedRoute(
|
||||
'users.verify-email-change',
|
||||
now()->addMinutes(60),
|
||||
[
|
||||
'user' => $user->getKey(),
|
||||
'email' => 'older@example.com',
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
// Act
|
||||
$response = $this->get($verificationUrl);
|
||||
|
||||
// Assert
|
||||
$response->assertForbidden();
|
||||
$user = $user->fresh();
|
||||
$this->assertEquals('current@example.com', $user->email);
|
||||
$this->assertEquals('newer@example.com', $user->pending_email);
|
||||
}
|
||||
}
|
||||
|
||||
253
tests/Unit/Endpoint/Web/UserEndpointTest.php
Normal file
253
tests/Unit/Endpoint/Web/UserEndpointTest.php
Normal file
@@ -0,0 +1,253 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Endpoint\Web;
|
||||
|
||||
use App\Http\Controllers\Web\UserController;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
|
||||
#[CoversClass(UserController::class)]
|
||||
class UserEndpointTest extends EndpointTestAbstract
|
||||
{
|
||||
public function test_pending_email_verification_updates_email_and_redirects_with_success_banner(): void
|
||||
{
|
||||
// Arrange
|
||||
$this->travelTo(Carbon::parse('2024-01-02 12:00:00', 'UTC'));
|
||||
$user = User::factory()->create([
|
||||
'email' => 'current@example.com',
|
||||
'pending_email' => 'new@example.com',
|
||||
'email_verified_at' => null,
|
||||
]);
|
||||
$this->actingAs($user);
|
||||
$verificationUrl = URL::temporarySignedRoute(
|
||||
'users.verify-email-change',
|
||||
now()->addMinutes(60),
|
||||
[
|
||||
'user' => $user->getKey(),
|
||||
'email' => 'NEW@EXAMPLE.COM',
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
// Act
|
||||
$response = $this->get($verificationUrl);
|
||||
|
||||
// Assert
|
||||
$response->assertRedirect(route('dashboard'));
|
||||
$response->assertSessionHas('bannerStyle', 'success');
|
||||
$response->assertSessionHas('bannerText', 'Your email address has been updated successfully.');
|
||||
$user->refresh();
|
||||
$this->assertSame('new@example.com', $user->email);
|
||||
$this->assertNull($user->pending_email);
|
||||
$this->assertTrue(now()->equalTo($user->email_verified_at));
|
||||
}
|
||||
|
||||
public function test_pending_email_verification_is_rejected_for_another_authenticated_user(): void
|
||||
{
|
||||
// Arrange
|
||||
$user = User::factory()->create([
|
||||
'email' => 'current@example.com',
|
||||
'pending_email' => 'new@example.com',
|
||||
]);
|
||||
$this->actingAs(User::factory()->create());
|
||||
$verificationUrl = URL::temporarySignedRoute(
|
||||
'users.verify-email-change',
|
||||
now()->addMinutes(60),
|
||||
[
|
||||
'user' => $user->getKey(),
|
||||
'email' => 'new@example.com',
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
// Act
|
||||
$response = $this->get($verificationUrl);
|
||||
|
||||
// Assert
|
||||
$response->assertForbidden();
|
||||
$user->refresh();
|
||||
$this->assertSame('current@example.com', $user->email);
|
||||
$this->assertSame('new@example.com', $user->pending_email);
|
||||
}
|
||||
|
||||
public function test_pending_email_verification_without_email_is_rejected(): void
|
||||
{
|
||||
// Arrange
|
||||
$user = User::factory()->create([
|
||||
'email' => 'current@example.com',
|
||||
'pending_email' => 'new@example.com',
|
||||
]);
|
||||
$this->actingAs($user);
|
||||
$verificationUrl = URL::temporarySignedRoute(
|
||||
'users.verify-email-change',
|
||||
now()->addMinutes(60),
|
||||
['user' => $user->getKey()],
|
||||
false
|
||||
);
|
||||
|
||||
// Act
|
||||
$response = $this->get($verificationUrl);
|
||||
|
||||
// Assert
|
||||
$response->assertForbidden();
|
||||
$user->refresh();
|
||||
$this->assertSame('current@example.com', $user->email);
|
||||
$this->assertSame('new@example.com', $user->pending_email);
|
||||
}
|
||||
|
||||
public function test_pending_email_verification_with_non_string_email_is_rejected(): void
|
||||
{
|
||||
// Arrange
|
||||
$user = User::factory()->create([
|
||||
'email' => 'current@example.com',
|
||||
'pending_email' => 'new@example.com',
|
||||
]);
|
||||
$this->actingAs($user);
|
||||
$verificationUrl = URL::temporarySignedRoute(
|
||||
'users.verify-email-change',
|
||||
now()->addMinutes(60),
|
||||
[
|
||||
'user' => $user->getKey(),
|
||||
'email' => ['new@example.com'],
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
// Act
|
||||
$response = $this->get($verificationUrl);
|
||||
|
||||
// Assert
|
||||
$response->assertForbidden();
|
||||
$user->refresh();
|
||||
$this->assertSame('current@example.com', $user->email);
|
||||
$this->assertSame('new@example.com', $user->pending_email);
|
||||
}
|
||||
|
||||
public function test_stale_pending_email_verification_link_is_rejected(): void
|
||||
{
|
||||
// Arrange
|
||||
$user = User::factory()->create([
|
||||
'email' => 'current@example.com',
|
||||
'pending_email' => 'newer@example.com',
|
||||
]);
|
||||
$this->actingAs($user);
|
||||
$verificationUrl = URL::temporarySignedRoute(
|
||||
'users.verify-email-change',
|
||||
now()->addMinutes(60),
|
||||
[
|
||||
'user' => $user->getKey(),
|
||||
'email' => 'older@example.com',
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
// Act
|
||||
$response = $this->get($verificationUrl);
|
||||
|
||||
// Assert
|
||||
$response->assertForbidden();
|
||||
$user->refresh();
|
||||
$this->assertSame('current@example.com', $user->email);
|
||||
$this->assertSame('newer@example.com', $user->pending_email);
|
||||
}
|
||||
|
||||
public function test_pending_email_verification_redirects_with_danger_banner_when_email_already_in_use(): void
|
||||
{
|
||||
// Arrange
|
||||
User::factory()->create([
|
||||
'email' => 'taken@example.com',
|
||||
'is_placeholder' => false,
|
||||
]);
|
||||
$user = User::factory()->create([
|
||||
'email' => 'current@example.com',
|
||||
'pending_email' => 'taken@example.com',
|
||||
]);
|
||||
$this->actingAs($user);
|
||||
$verificationUrl = URL::temporarySignedRoute(
|
||||
'users.verify-email-change',
|
||||
now()->addMinutes(60),
|
||||
[
|
||||
'user' => $user->getKey(),
|
||||
'email' => 'taken@example.com',
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
// Act
|
||||
$response = $this->get($verificationUrl);
|
||||
|
||||
// Assert
|
||||
$response->assertRedirect(route('dashboard'));
|
||||
$response->assertSessionHas('bannerStyle', 'danger');
|
||||
$response->assertSessionHas('bannerText', 'The email address is already in use.');
|
||||
$user->refresh();
|
||||
$this->assertSame('current@example.com', $user->email);
|
||||
$this->assertSame('taken@example.com', $user->pending_email);
|
||||
}
|
||||
|
||||
public function test_pending_email_verification_ignores_placeholder_users_with_the_same_email(): void
|
||||
{
|
||||
// Arrange
|
||||
User::factory()->placeholder()->create([
|
||||
'email' => 'new@example.com',
|
||||
]);
|
||||
$user = User::factory()->create([
|
||||
'email' => 'current@example.com',
|
||||
'pending_email' => 'new@example.com',
|
||||
'email_verified_at' => null,
|
||||
]);
|
||||
$this->actingAs($user);
|
||||
$verificationUrl = URL::temporarySignedRoute(
|
||||
'users.verify-email-change',
|
||||
now()->addMinutes(60),
|
||||
[
|
||||
'user' => $user->getKey(),
|
||||
'email' => 'new@example.com',
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
// Act
|
||||
$response = $this->get($verificationUrl);
|
||||
|
||||
// Assert
|
||||
$response->assertRedirect(route('dashboard'));
|
||||
$response->assertSessionHas('bannerStyle', 'success');
|
||||
$user->refresh();
|
||||
$this->assertSame('new@example.com', $user->email);
|
||||
$this->assertNull($user->pending_email);
|
||||
$this->assertNotNull($user->email_verified_at);
|
||||
}
|
||||
|
||||
public function test_pending_email_verification_with_invalid_signature_is_rejected(): void
|
||||
{
|
||||
// Arrange
|
||||
$user = User::factory()->create([
|
||||
'email' => 'current@example.com',
|
||||
'pending_email' => 'new@example.com',
|
||||
]);
|
||||
$this->actingAs($user);
|
||||
$verificationUrl = URL::temporarySignedRoute(
|
||||
'users.verify-email-change',
|
||||
now()->addMinutes(60),
|
||||
[
|
||||
'user' => $user->getKey(),
|
||||
'email' => 'new@example.com',
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
// Act
|
||||
$response = $this->get($verificationUrl.'&invalid');
|
||||
|
||||
// Assert
|
||||
$response->assertForbidden();
|
||||
$user->refresh();
|
||||
$this->assertSame('current@example.com', $user->email);
|
||||
$this->assertSame('new@example.com', $user->pending_email);
|
||||
}
|
||||
}
|
||||
131
tests/Unit/Service/Dto/UserAgentDtoTest.php
Normal file
131
tests/Unit/Service/Dto/UserAgentDtoTest.php
Normal file
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Service\Dto;
|
||||
|
||||
use App\Service\Dto\UserAgentDto;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use Tests\TestCase;
|
||||
|
||||
#[CoversClass(UserAgentDto::class)]
|
||||
class UserAgentDtoTest extends TestCase
|
||||
{
|
||||
public function test_chrome_on_windows_is_detected_as_a_desktop_browser(): void
|
||||
{
|
||||
// Arrange
|
||||
$userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36';
|
||||
$agent = new UserAgentDto;
|
||||
$agent->setUserAgent($userAgent);
|
||||
|
||||
// Act
|
||||
$platform = $agent->platform();
|
||||
$browser = $agent->browser();
|
||||
$isDesktop = $agent->isDesktop();
|
||||
|
||||
// Assert
|
||||
$this->assertSame('Windows', $platform);
|
||||
$this->assertSame('Chrome', $browser);
|
||||
$this->assertTrue($isDesktop);
|
||||
}
|
||||
|
||||
public function test_edge_is_detected_before_chrome(): void
|
||||
{
|
||||
// Arrange
|
||||
$userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0';
|
||||
$agent = new UserAgentDto;
|
||||
$agent->setUserAgent($userAgent);
|
||||
|
||||
// Act
|
||||
$browser = $agent->browser();
|
||||
|
||||
// Assert
|
||||
$this->assertSame('Edge', $browser);
|
||||
}
|
||||
|
||||
public function test_iphone_safari_is_detected_as_a_non_desktop_browser(): void
|
||||
{
|
||||
// Arrange
|
||||
$userAgent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1';
|
||||
$agent = new UserAgentDto;
|
||||
$agent->setUserAgent($userAgent);
|
||||
|
||||
// Act
|
||||
$platform = $agent->platform();
|
||||
$browser = $agent->browser();
|
||||
$isDesktop = $agent->isDesktop();
|
||||
|
||||
// Assert
|
||||
$this->assertSame('iOS', $platform);
|
||||
$this->assertSame('Safari', $browser);
|
||||
$this->assertFalse($isDesktop);
|
||||
}
|
||||
|
||||
public function test_ipad_is_detected_as_non_desktop(): void
|
||||
{
|
||||
// Arrange
|
||||
$userAgent = 'Mozilla/5.0 (iPad; CPU OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1';
|
||||
$agent = new UserAgentDto;
|
||||
$agent->setUserAgent($userAgent);
|
||||
|
||||
// Act
|
||||
$isDesktop = $agent->isDesktop();
|
||||
|
||||
// Assert
|
||||
$this->assertFalse($isDesktop);
|
||||
}
|
||||
|
||||
public function test_unknown_user_agent_has_no_platform_or_browser_and_is_a_desktop(): void
|
||||
{
|
||||
// Arrange
|
||||
$agent = new UserAgentDto;
|
||||
$agent->setUserAgent('CustomClient/1.0');
|
||||
|
||||
// Act
|
||||
$platform = $agent->platform();
|
||||
$browser = $agent->browser();
|
||||
$isDesktop = $agent->isDesktop();
|
||||
|
||||
// Assert
|
||||
$this->assertNull($platform);
|
||||
$this->assertNull($browser);
|
||||
$this->assertTrue($isDesktop);
|
||||
}
|
||||
|
||||
public function test_cloudfront_desktop_header_is_detected_as_desktop(): void
|
||||
{
|
||||
// Arrange
|
||||
$agent = new UserAgentDto;
|
||||
$agent->setUserAgent('Amazon CloudFront');
|
||||
$agent->setHttpHeaders([
|
||||
'HTTP_CLOUDFRONT_IS_DESKTOP_VIEWER' => 'true',
|
||||
]);
|
||||
|
||||
// Act
|
||||
$isDesktop = $agent->isDesktop();
|
||||
|
||||
// Assert
|
||||
$this->assertTrue($isDesktop);
|
||||
}
|
||||
|
||||
public function test_cached_values_are_resolved_for_the_current_user_agent(): void
|
||||
{
|
||||
// Arrange
|
||||
$agent = new UserAgentDto;
|
||||
$agent->setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0 Safari/537.36');
|
||||
$agent->platform();
|
||||
$agent->browser();
|
||||
$agent->isDesktop();
|
||||
$agent->setUserAgent('Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) Version/17.0 Mobile/15E148 Safari/604.1');
|
||||
|
||||
// Act
|
||||
$platform = $agent->platform();
|
||||
$browser = $agent->browser();
|
||||
$isDesktop = $agent->isDesktop();
|
||||
|
||||
// Assert
|
||||
$this->assertSame('iOS', $platform);
|
||||
$this->assertSame('Safari', $browser);
|
||||
$this->assertFalse($isDesktop);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user