fedi-feed-router/backend/tests/Unit/Services/Auth/LemmyAuthServiceTest.php

300 lines
9.8 KiB
PHP
Raw Normal View History

2025-08-06 21:49:13 +02:00
<?php
namespace Tests\Unit\Services\Auth;
use App\Enums\PlatformEnum;
use App\Exceptions\PlatformAuthException;
use App\Models\PlatformAccount;
use App\Modules\Lemmy\Services\LemmyApiService;
use App\Services\Auth\LemmyAuthService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Cache;
use Mockery;
use Tests\TestCase;
class LemmyAuthServiceTest extends TestCase
{
use RefreshDatabase;
protected function tearDown(): void
{
Mockery::close();
parent::tearDown();
}
public function test_get_token_returns_cached_token_when_available(): void
{
$account = PlatformAccount::factory()->create([
'username' => 'testuser',
'password' => 'testpass',
'instance_url' => 'https://lemmy.test'
]);
$cachedToken = 'cached-jwt-token';
$cacheKey = "lemmy_jwt_token_{$account->id}";
Cache::shouldReceive('get')
->once()
->with($cacheKey)
->andReturn($cachedToken);
$result = LemmyAuthService::getToken($account);
$this->assertEquals($cachedToken, $result);
}
public function test_get_token_throws_exception_when_username_missing(): void
{
// Create account with valid data first, then modify username property
$account = PlatformAccount::factory()->create([
'username' => 'testuser',
'password' => 'testpass',
'instance_url' => 'https://lemmy.test'
]);
2025-08-10 01:26:56 +02:00
2025-08-06 21:49:13 +02:00
// Use reflection to set username to null to bypass validation
$reflection = new \ReflectionClass($account);
$property = $reflection->getProperty('attributes');
$property->setAccessible(true);
$attributes = $property->getValue($account);
$attributes['username'] = null;
$property->setValue($account, $attributes);
// Mock cache to return null (no cached token)
Cache::shouldReceive('get')
->once()
->andReturn(null);
$this->expectException(PlatformAuthException::class);
$this->expectExceptionMessage('Missing credentials for account: ');
LemmyAuthService::getToken($account);
}
public function test_get_token_throws_exception_when_password_missing(): void
{
// Create account with valid data first, then modify password property
$account = PlatformAccount::factory()->create([
'username' => 'testuser',
'password' => 'testpass',
'instance_url' => 'https://lemmy.test'
]);
2025-08-10 01:26:56 +02:00
2025-08-06 21:49:13 +02:00
// Use reflection to set password to null to bypass validation
$reflection = new \ReflectionClass($account);
$property = $reflection->getProperty('attributes');
$property->setAccessible(true);
$attributes = $property->getValue($account);
$attributes['password'] = null;
$property->setValue($account, $attributes);
// Mock cache to return null (no cached token)
Cache::shouldReceive('get')
->once()
->andReturn(null);
$this->expectException(PlatformAuthException::class);
$this->expectExceptionMessage('Missing credentials for account: testuser');
LemmyAuthService::getToken($account);
}
public function test_get_token_throws_exception_when_instance_url_missing(): void
{
// Create account with valid data first, then modify instance_url property
$account = PlatformAccount::factory()->create([
'username' => 'testuser',
'password' => 'testpass',
'instance_url' => 'https://lemmy.test'
]);
2025-08-10 01:26:56 +02:00
2025-08-06 21:49:13 +02:00
// Use reflection to set instance_url to null to bypass validation
$reflection = new \ReflectionClass($account);
$property = $reflection->getProperty('attributes');
$property->setAccessible(true);
$attributes = $property->getValue($account);
$attributes['instance_url'] = null;
$property->setValue($account, $attributes);
// Mock cache to return null (no cached token)
Cache::shouldReceive('get')
->once()
->andReturn(null);
$this->expectException(PlatformAuthException::class);
$this->expectExceptionMessage('Missing credentials for account: testuser');
LemmyAuthService::getToken($account);
}
public function test_get_token_successfully_authenticates_and_caches_token(): void
{
2025-08-10 01:26:56 +02:00
$account = PlatformAccount::factory()->create([
'username' => 'testuser',
'password' => 'testpass',
'instance_url' => 'https://lemmy.test'
]);
$cacheKey = "lemmy_jwt_token_{$account->id}";
// No cached token initially
Cache::shouldReceive('get')
->once()
->with($cacheKey)
->andReturn(null);
// Expect token to be cached for 3000 seconds
Cache::shouldReceive('put')
->once()
->with($cacheKey, 'jwt-123', 3000);
// Mock new LemmyApiService(...) instance to return a token
$apiMock = Mockery::mock('overload:' . LemmyApiService::class);
$apiMock->shouldReceive('login')
->once()
->with('testuser', 'testpass')
->andReturn('jwt-123');
$result = LemmyAuthService::getToken($account);
$this->assertEquals('jwt-123', $result);
2025-08-06 21:49:13 +02:00
}
public function test_get_token_throws_exception_when_login_fails(): void
{
2025-08-10 01:26:56 +02:00
$account = PlatformAccount::factory()->create([
'username' => 'failingUser',
'password' => 'badpass',
'instance_url' => 'https://lemmy.test'
]);
$cacheKey = "lemmy_jwt_token_{$account->id}";
Cache::shouldReceive('get')
->once()
->with($cacheKey)
->andReturn(null);
// Mock API to return null (login failed)
$apiMock = Mockery::mock('overload:' . LemmyApiService::class);
$apiMock->shouldReceive('login')
->once()
->with('failingUser', 'badpass')
->andReturn(null);
$this->expectException(PlatformAuthException::class);
$this->expectExceptionMessage('Login failed for account: failingUser');
LemmyAuthService::getToken($account);
2025-08-06 21:49:13 +02:00
}
public function test_get_token_throws_exception_when_login_returns_false(): void
{
2025-08-10 01:26:56 +02:00
$account = PlatformAccount::factory()->create([
'username' => 'emptyUser',
'password' => 'pass',
'instance_url' => 'https://lemmy.test'
]);
$cacheKey = "lemmy_jwt_token_{$account->id}";
Cache::shouldReceive('get')
->once()
->with($cacheKey)
->andReturn(null);
// Mock API to return an empty string (falsy)
$apiMock = Mockery::mock('overload:' . LemmyApiService::class);
$apiMock->shouldReceive('login')
->once()
->with('emptyUser', 'pass')
->andReturn('');
$this->expectException(PlatformAuthException::class);
$this->expectExceptionMessage('Login failed for account: emptyUser');
LemmyAuthService::getToken($account);
2025-08-06 21:49:13 +02:00
}
public function test_get_token_uses_correct_cache_duration(): void
{
2025-08-10 01:26:56 +02:00
$account = PlatformAccount::factory()->create([
'username' => 'cacheUser',
'password' => 'secret',
'instance_url' => 'https://lemmy.test'
]);
$cacheKey = "lemmy_jwt_token_{$account->id}";
Cache::shouldReceive('get')
->once()
->with($cacheKey)
->andReturn(null);
Cache::shouldReceive('put')
->once()
->with($cacheKey, 'xyz', 3000);
$apiMock = Mockery::mock('overload:' . LemmyApiService::class);
$apiMock->shouldReceive('login')->once()->andReturn('xyz');
$token = LemmyAuthService::getToken($account);
$this->assertEquals('xyz', $token);
2025-08-06 21:49:13 +02:00
}
public function test_get_token_uses_account_specific_cache_key(): void
{
$account1 = PlatformAccount::factory()->create(['username' => 'user1']);
$account2 = PlatformAccount::factory()->create(['username' => 'user2']);
$cacheKey1 = "lemmy_jwt_token_{$account1->id}";
$cacheKey2 = "lemmy_jwt_token_{$account2->id}";
Cache::shouldReceive('get')
->once()
->with($cacheKey1)
->andReturn('token1');
Cache::shouldReceive('get')
->once()
->with($cacheKey2)
->andReturn('token2');
$result1 = LemmyAuthService::getToken($account1);
$result2 = LemmyAuthService::getToken($account2);
$this->assertEquals('token1', $result1);
$this->assertEquals('token2', $result2);
}
public function test_platform_auth_exception_contains_correct_platform(): void
{
// Create account with valid data first, then modify username property
$account = PlatformAccount::factory()->create([
'username' => 'testuser',
'password' => 'testpass',
'instance_url' => 'https://lemmy.test'
]);
2025-08-10 01:26:56 +02:00
2025-08-06 21:49:13 +02:00
// Use reflection to set username to null to bypass validation
$reflection = new \ReflectionClass($account);
$property = $reflection->getProperty('attributes');
$property->setAccessible(true);
$attributes = $property->getValue($account);
$attributes['username'] = null;
$property->setValue($account, $attributes);
// Mock cache to return null (no cached token)
Cache::shouldReceive('get')
->once()
->andReturn(null);
try {
LemmyAuthService::getToken($account);
$this->fail('Expected PlatformAuthException to be thrown');
} catch (PlatformAuthException $e) {
$this->assertEquals(PlatformEnum::LEMMY, $e->getPlatform());
}
}
2025-08-10 01:26:56 +02:00
}