Http::response('', 500)]); $account = PlatformAccount::factory()->create([ 'username' => 'testuser', 'password' => 'testpass', 'instance_url' => 'https://lemmy.test' ]); $cachedToken = 'cached-jwt-token'; $cacheKey = "lemmy_jwt_token_{$account->id}"; // Put token in cache using Laravel's testing cache cache()->put($cacheKey, $cachedToken, 3000); $result = LemmyAuthService::getToken($account); $this->assertEquals($cachedToken, $result); } public function test_get_token_throws_exception_when_username_missing(): void { // Mock HTTP to prevent any external calls (not needed since it throws before API call) Http::fake(['*' => Http::response('', 500)]); // Create account with valid data first, then modify username property $account = PlatformAccount::factory()->create([ 'username' => 'testuser', 'password' => 'testpass', 'instance_url' => 'https://lemmy.test' ]); // 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); // Ensure no cached token exists cache()->forget("lemmy_jwt_token_{$account->id}"); $this->expectException(PlatformAuthException::class); $this->expectExceptionMessage('Missing credentials for account: '); LemmyAuthService::getToken($account); } public function test_get_token_throws_exception_when_password_missing(): void { // Mock HTTP to prevent any external calls Http::fake(['*' => Http::response('', 500)]); // Create account with valid data first, then modify password property $account = PlatformAccount::factory()->create([ 'username' => 'testuser', 'password' => 'testpass', 'instance_url' => 'https://lemmy.test' ]); // 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); // Ensure no cached token exists cache()->forget("lemmy_jwt_token_{$account->id}"); $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 { // Mock HTTP to prevent any external calls Http::fake(['*' => Http::response('', 500)]); // Create account with valid data first, then modify instance_url property $account = PlatformAccount::factory()->create([ 'username' => 'testuser', 'password' => 'testpass', 'instance_url' => 'https://lemmy.test' ]); // 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); // Ensure no cached token exists cache()->forget("lemmy_jwt_token_{$account->id}"); $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 { // Mock successful HTTP response for both HTTPS and HTTP (fallback) Http::fake([ 'https://lemmy.test/api/v3/user/login' => Http::response(['jwt' => 'jwt-123'], 200), 'http://lemmy.test/api/v3/user/login' => Http::response(['jwt' => 'jwt-123'], 200) ]); $account = PlatformAccount::factory()->create([ 'username' => 'testuser', 'password' => 'testpass', 'instance_url' => 'https://lemmy.test' ]); $cacheKey = "lemmy_jwt_token_{$account->id}"; // Ensure no cached token exists initially cache()->forget($cacheKey); $result = LemmyAuthService::getToken($account); $this->assertEquals('jwt-123', $result); // Verify token was cached $this->assertEquals('jwt-123', cache()->get($cacheKey)); } public function test_get_token_throws_exception_when_login_fails(): void { // Mock failed HTTP response for both HTTPS and HTTP Http::fake([ 'https://lemmy.test/api/v3/user/login' => Http::response(['error' => 'Invalid credentials'], 401), 'http://lemmy.test/api/v3/user/login' => Http::response(['error' => 'Invalid credentials'], 401) ]); $account = PlatformAccount::factory()->create([ 'username' => 'failingUser', 'password' => 'badpass', 'instance_url' => 'https://lemmy.test' ]); $cacheKey = "lemmy_jwt_token_{$account->id}"; // Ensure no cached token exists Cache::forget($cacheKey); $this->expectException(PlatformAuthException::class); $this->expectExceptionMessage('Login failed for account: failingUser'); LemmyAuthService::getToken($account); } public function test_get_token_throws_exception_when_login_returns_false(): void { // Mock response with empty/missing JWT for both HTTPS and HTTP Http::fake([ 'https://lemmy.test/api/v3/user/login' => Http::response(['success' => false], 200), 'http://lemmy.test/api/v3/user/login' => Http::response(['success' => false], 200) ]); $account = PlatformAccount::factory()->create([ 'username' => 'emptyUser', 'password' => 'pass', 'instance_url' => 'https://lemmy.test' ]); $cacheKey = "lemmy_jwt_token_{$account->id}"; // Ensure no cached token exists Cache::forget($cacheKey); $this->expectException(PlatformAuthException::class); $this->expectExceptionMessage('Login failed for account: emptyUser'); LemmyAuthService::getToken($account); } public function test_get_token_uses_correct_cache_duration(): void { // Mock successful HTTP response for both HTTPS and HTTP Http::fake([ 'https://lemmy.test/api/v3/user/login' => Http::response(['jwt' => 'xyz'], 200), 'http://lemmy.test/api/v3/user/login' => Http::response(['jwt' => 'xyz'], 200) ]); $account = PlatformAccount::factory()->create([ 'username' => 'cacheUser', 'password' => 'secret', 'instance_url' => 'https://lemmy.test' ]); $cacheKey = "lemmy_jwt_token_{$account->id}"; // Ensure no cached token exists initially cache()->forget($cacheKey); $token = LemmyAuthService::getToken($account); $this->assertEquals('xyz', $token); // Verify token was cached $this->assertEquals('xyz', cache()->get($cacheKey)); } public function test_get_token_uses_account_specific_cache_key(): void { // Mock HTTP to prevent any external calls Http::fake(['*' => Http::response('', 500)]); $account1 = PlatformAccount::factory()->create(['username' => 'user1']); $account2 = PlatformAccount::factory()->create(['username' => 'user2']); $cacheKey1 = "lemmy_jwt_token_{$account1->id}"; $cacheKey2 = "lemmy_jwt_token_{$account2->id}"; // Set up different cached tokens for each account cache()->put($cacheKey1, 'token1', 3000); cache()->put($cacheKey2, 'token2', 3000); $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 { // Mock HTTP to prevent any external calls Http::fake(['*' => Http::response('', 500)]); // Create account with valid data first, then modify username property $account = PlatformAccount::factory()->create([ 'username' => 'testuser', 'password' => 'testpass', 'instance_url' => 'https://lemmy.test' ]); // 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); // Ensure no cached token exists cache()->forget("lemmy_jwt_token_{$account->id}"); try { LemmyAuthService::getToken($account); $this->fail('Expected PlatformAuthException to be thrown'); } catch (PlatformAuthException $e) { $this->assertEquals(PlatformEnum::LEMMY, $e->getPlatform()); } } }