2025-08-10 04:16:53 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace Tests\Unit\Modules\Lemmy\Services;
|
|
|
|
|
|
2025-08-15 16:39:18 +02:00
|
|
|
use Domains\Platform\Api\Lemmy\LemmyApiService;
|
|
|
|
|
use Domains\Platform\Models\PlatformChannelPost;
|
|
|
|
|
use Domains\Platform\Enums\PlatformEnum;
|
2025-08-10 04:16:53 +02:00
|
|
|
use Illuminate\Support\Facades\Http;
|
|
|
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
|
use Tests\TestCase;
|
|
|
|
|
use Mockery;
|
|
|
|
|
use Exception;
|
|
|
|
|
|
|
|
|
|
class LemmyApiServiceTest extends TestCase
|
|
|
|
|
{
|
|
|
|
|
protected function tearDown(): void
|
|
|
|
|
{
|
|
|
|
|
parent::tearDown();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_constructor_sets_instance(): void
|
|
|
|
|
{
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
2025-08-11 18:26:00 +02:00
|
|
|
|
2025-08-10 04:16:53 +02:00
|
|
|
$reflection = new \ReflectionClass($service);
|
|
|
|
|
$property = $reflection->getProperty('instance');
|
|
|
|
|
$property->setAccessible(true);
|
2025-08-11 18:26:00 +02:00
|
|
|
|
2025-08-10 04:16:53 +02:00
|
|
|
$this->assertEquals('lemmy.world', $property->getValue($service));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_login_with_https_success(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'https://lemmy.world/api/v3/user/login' => Http::response(['jwt' => 'test-token'], 200)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
$token = $service->login('user', 'pass');
|
|
|
|
|
|
|
|
|
|
$this->assertEquals('test-token', $token);
|
|
|
|
|
|
|
|
|
|
Http::assertSent(function ($request) {
|
|
|
|
|
return $request->url() === 'https://lemmy.world/api/v3/user/login'
|
|
|
|
|
&& $request['username_or_email'] === 'user'
|
|
|
|
|
&& $request['password'] === 'pass';
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_login_falls_back_to_http_on_https_failure(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'https://lemmy.world/api/v3/user/login' => Http::response('', 500),
|
|
|
|
|
'http://lemmy.world/api/v3/user/login' => Http::response(['jwt' => 'http-token'], 200)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
$token = $service->login('user', 'pass');
|
|
|
|
|
|
|
|
|
|
$this->assertEquals('http-token', $token);
|
|
|
|
|
|
|
|
|
|
Http::assertSentCount(2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_login_with_explicit_http_scheme(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'http://localhost/api/v3/user/login' => Http::response(['jwt' => 'local-token'], 200)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('http://localhost');
|
|
|
|
|
$token = $service->login('user', 'pass');
|
|
|
|
|
|
|
|
|
|
$this->assertEquals('local-token', $token);
|
|
|
|
|
|
|
|
|
|
Http::assertSent(function ($request) {
|
|
|
|
|
return $request->url() === 'http://localhost/api/v3/user/login';
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_login_with_explicit_https_scheme(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'https://secure.lemmy/api/v3/user/login' => Http::response(['jwt' => 'secure-token'], 200)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('https://secure.lemmy');
|
|
|
|
|
$token = $service->login('user', 'pass');
|
|
|
|
|
|
|
|
|
|
$this->assertEquals('secure-token', $token);
|
|
|
|
|
|
|
|
|
|
Http::assertSent(function ($request) {
|
|
|
|
|
return $request->url() === 'https://secure.lemmy/api/v3/user/login';
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_login_returns_null_on_unsuccessful_response(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'*' => Http::response(['error' => 'Invalid credentials'], 401)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
Log::shouldReceive('error')->twice(); // Once for HTTPS, once for HTTP fallback
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
$token = $service->login('user', 'wrong');
|
|
|
|
|
|
|
|
|
|
$this->assertNull($token);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_login_handles_rate_limit_error(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'*' => Http::response('{"error":"rate_limit_error"}', 429)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
// Expecting 4 error logs:
|
|
|
|
|
// 1. 'Lemmy login failed' for HTTPS attempt
|
|
|
|
|
// 2. 'Lemmy login exception' for catching the rate limit exception on HTTPS
|
2025-08-11 18:26:00 +02:00
|
|
|
// 3. 'Lemmy login failed' for HTTP attempt
|
2025-08-10 04:16:53 +02:00
|
|
|
// 4. 'Lemmy login exception' for catching the rate limit exception on HTTP
|
|
|
|
|
Log::shouldReceive('error')->times(4);
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
$result = $service->login('user', 'pass');
|
2025-08-11 18:26:00 +02:00
|
|
|
|
2025-08-10 04:16:53 +02:00
|
|
|
// Since the exception is caught and HTTP is tried, then that also fails,
|
|
|
|
|
// the method returns null instead of throwing
|
|
|
|
|
$this->assertNull($result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_login_returns_null_when_jwt_missing_from_response(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'*' => Http::response(['success' => true], 200)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
$token = $service->login('user', 'pass');
|
|
|
|
|
|
|
|
|
|
$this->assertNull($token);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_login_handles_exception_and_returns_null(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake(function () {
|
|
|
|
|
throw new Exception('Network error');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Log::shouldReceive('error')->twice();
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
$token = $service->login('user', 'pass');
|
|
|
|
|
|
|
|
|
|
$this->assertNull($token);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_get_community_id_success(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'*' => Http::response([
|
|
|
|
|
'community_view' => [
|
|
|
|
|
'community' => ['id' => 123]
|
|
|
|
|
]
|
|
|
|
|
], 200)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
$id = $service->getCommunityId('test-community', 'token');
|
|
|
|
|
|
|
|
|
|
$this->assertEquals(123, $id);
|
|
|
|
|
|
|
|
|
|
Http::assertSent(function ($request) {
|
|
|
|
|
return str_contains($request->url(), '/api/v3/community')
|
|
|
|
|
&& str_contains($request->url(), 'name=test-community')
|
|
|
|
|
&& $request->header('Authorization')[0] === 'Bearer token';
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_get_community_id_throws_on_unsuccessful_response(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'*' => Http::response('Not found', 404)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
Log::shouldReceive('error')->once();
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
|
|
|
|
|
$this->expectException(Exception::class);
|
|
|
|
|
$this->expectExceptionMessage('Failed to fetch community: 404');
|
|
|
|
|
|
|
|
|
|
$service->getCommunityId('missing', 'token');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_get_community_id_throws_when_community_not_in_response(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'*' => Http::response(['success' => true], 200)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
Log::shouldReceive('error')->once();
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
|
|
|
|
|
$this->expectException(Exception::class);
|
|
|
|
|
$this->expectExceptionMessage('Community not found');
|
|
|
|
|
|
|
|
|
|
$service->getCommunityId('test', 'token');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_sync_channel_posts_success(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'*' => Http::response([
|
|
|
|
|
'posts' => [
|
|
|
|
|
[
|
|
|
|
|
'post' => [
|
|
|
|
|
'id' => 1,
|
|
|
|
|
'url' => 'https://example.com/1',
|
|
|
|
|
'name' => 'Post 1',
|
|
|
|
|
'published' => '2024-01-01T00:00:00Z'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'post' => [
|
|
|
|
|
'id' => 2,
|
|
|
|
|
'url' => 'https://example.com/2',
|
|
|
|
|
'name' => 'Post 2',
|
|
|
|
|
'published' => '2024-01-02T00:00:00Z'
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
], 200)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
Log::shouldReceive('info')->once()->with('Synced channel posts', Mockery::any());
|
|
|
|
|
|
|
|
|
|
$mockPost = Mockery::mock('alias:' . PlatformChannelPost::class);
|
|
|
|
|
$mockPost->shouldReceive('storePost')
|
|
|
|
|
->twice()
|
|
|
|
|
->with(
|
|
|
|
|
PlatformEnum::LEMMY,
|
|
|
|
|
Mockery::any(),
|
|
|
|
|
'test-community',
|
|
|
|
|
Mockery::any(),
|
|
|
|
|
Mockery::any(),
|
|
|
|
|
Mockery::any(),
|
|
|
|
|
Mockery::any()
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
$service->syncChannelPosts('token', 42, 'test-community');
|
|
|
|
|
|
|
|
|
|
Http::assertSent(function ($request) {
|
|
|
|
|
return str_contains($request->url(), '/api/v3/post/list')
|
|
|
|
|
&& str_contains($request->url(), 'community_id=42')
|
|
|
|
|
&& str_contains($request->url(), 'limit=50')
|
|
|
|
|
&& str_contains($request->url(), 'sort=New');
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_sync_channel_posts_handles_unsuccessful_response(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'*' => Http::response('Error', 500)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
Log::shouldReceive('warning')->once()->with('Failed to sync channel posts', Mockery::any());
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
$service->syncChannelPosts('token', 42, 'test-community');
|
|
|
|
|
|
|
|
|
|
Http::assertSentCount(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_sync_channel_posts_handles_exception(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake(function () {
|
|
|
|
|
throw new Exception('Network error');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Log::shouldReceive('error')->once()->with('Exception while syncing channel posts', Mockery::any());
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
$service->syncChannelPosts('token', 42, 'test-community');
|
2025-08-11 18:26:00 +02:00
|
|
|
|
2025-08-10 04:16:53 +02:00
|
|
|
// Assert that the method completes without throwing
|
|
|
|
|
$this->assertTrue(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_create_post_with_all_parameters(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'*' => Http::response(['post_view' => ['post' => ['id' => 999]]], 200)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
$result = $service->createPost(
|
|
|
|
|
'token',
|
|
|
|
|
'Test Title',
|
|
|
|
|
'Test Body',
|
|
|
|
|
42,
|
|
|
|
|
'https://example.com',
|
|
|
|
|
'https://example.com/thumb.jpg',
|
|
|
|
|
5
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$this->assertEquals(['post_view' => ['post' => ['id' => 999]]], $result);
|
|
|
|
|
|
|
|
|
|
Http::assertSent(function ($request) {
|
|
|
|
|
$data = $request->data();
|
|
|
|
|
return $request->url() === 'https://lemmy.world/api/v3/post'
|
|
|
|
|
&& $data['name'] === 'Test Title'
|
|
|
|
|
&& $data['body'] === 'Test Body'
|
|
|
|
|
&& $data['community_id'] === 42
|
|
|
|
|
&& $data['url'] === 'https://example.com'
|
|
|
|
|
&& $data['custom_thumbnail'] === 'https://example.com/thumb.jpg'
|
|
|
|
|
&& $data['language_id'] === 5;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_create_post_with_minimal_parameters(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'*' => Http::response(['post_view' => ['post' => ['id' => 888]]], 200)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
$result = $service->createPost(
|
|
|
|
|
'token',
|
|
|
|
|
'Title Only',
|
|
|
|
|
'Body Only',
|
|
|
|
|
42
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$this->assertEquals(['post_view' => ['post' => ['id' => 888]]], $result);
|
|
|
|
|
|
|
|
|
|
Http::assertSent(function ($request) {
|
|
|
|
|
$data = $request->data();
|
|
|
|
|
return $request->url() === 'https://lemmy.world/api/v3/post'
|
|
|
|
|
&& $data['name'] === 'Title Only'
|
|
|
|
|
&& $data['body'] === 'Body Only'
|
|
|
|
|
&& $data['community_id'] === 42
|
|
|
|
|
&& !isset($data['url'])
|
|
|
|
|
&& !isset($data['custom_thumbnail'])
|
|
|
|
|
&& !isset($data['language_id']);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_create_post_throws_on_unsuccessful_response(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'*' => Http::response('Forbidden', 403)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
Log::shouldReceive('error')->once();
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
|
|
|
|
|
$this->expectException(Exception::class);
|
|
|
|
|
$this->expectExceptionMessage('Failed to create post: 403');
|
|
|
|
|
|
|
|
|
|
$service->createPost('token', 'Title', 'Body', 42);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_get_languages_success(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'*' => Http::response([
|
|
|
|
|
'all_languages' => [
|
|
|
|
|
['id' => 1, 'code' => 'en', 'name' => 'English'],
|
|
|
|
|
['id' => 2, 'code' => 'fr', 'name' => 'French']
|
|
|
|
|
]
|
|
|
|
|
], 200)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
$languages = $service->getLanguages();
|
|
|
|
|
|
|
|
|
|
$this->assertCount(2, $languages);
|
|
|
|
|
$this->assertEquals('en', $languages[0]['code']);
|
|
|
|
|
$this->assertEquals('fr', $languages[1]['code']);
|
|
|
|
|
|
|
|
|
|
Http::assertSent(function ($request) {
|
|
|
|
|
return str_contains($request->url(), '/api/v3/site');
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_get_languages_returns_empty_array_on_failure(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'*' => Http::response('Error', 500)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
Log::shouldReceive('warning')->once();
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
$languages = $service->getLanguages();
|
|
|
|
|
|
|
|
|
|
$this->assertEquals([], $languages);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_get_languages_handles_exception(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake(function () {
|
|
|
|
|
throw new Exception('Network error');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Log::shouldReceive('error')->once();
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
$languages = $service->getLanguages();
|
|
|
|
|
|
|
|
|
|
$this->assertEquals([], $languages);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_get_languages_returns_empty_when_all_languages_missing(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'*' => Http::response(['site_view' => []], 200)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
$languages = $service->getLanguages();
|
|
|
|
|
|
|
|
|
|
$this->assertEquals([], $languages);
|
|
|
|
|
}
|
2025-08-16 11:34:52 +02:00
|
|
|
|
|
|
|
|
public function test_list_communities_success_with_default_parameters(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'*' => Http::response([
|
|
|
|
|
'communities' => [
|
|
|
|
|
[
|
|
|
|
|
'community' => [
|
|
|
|
|
'id' => 1,
|
|
|
|
|
'name' => 'technology',
|
|
|
|
|
'title' => 'Technology Community',
|
|
|
|
|
'description' => 'All about tech',
|
|
|
|
|
'nsfw' => false
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'community' => [
|
|
|
|
|
'id' => 2,
|
|
|
|
|
'name' => 'news',
|
|
|
|
|
'title' => 'News Community',
|
|
|
|
|
'description' => 'Latest news',
|
|
|
|
|
'nsfw' => false
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
], 200)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
$result = $service->listCommunities();
|
|
|
|
|
|
|
|
|
|
$this->assertArrayHasKey('communities', $result);
|
|
|
|
|
$this->assertCount(2, $result['communities']);
|
|
|
|
|
$this->assertEquals('technology', $result['communities'][0]['community']['name']);
|
|
|
|
|
$this->assertEquals('news', $result['communities'][1]['community']['name']);
|
|
|
|
|
|
|
|
|
|
Http::assertSent(function ($request) {
|
|
|
|
|
return str_contains($request->url(), '/api/v3/community/list')
|
|
|
|
|
&& str_contains($request->url(), 'type_=Local')
|
|
|
|
|
&& str_contains($request->url(), 'sort=Active')
|
|
|
|
|
&& str_contains($request->url(), 'limit=50')
|
|
|
|
|
&& str_contains($request->url(), 'page=1')
|
|
|
|
|
&& str_contains($request->url(), 'show_nsfw=');
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_list_communities_success_with_custom_parameters(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'*' => Http::response([
|
|
|
|
|
'communities' => [
|
|
|
|
|
[
|
|
|
|
|
'community' => [
|
|
|
|
|
'id' => 3,
|
|
|
|
|
'name' => 'gaming',
|
|
|
|
|
'title' => 'Gaming Community',
|
|
|
|
|
'description' => 'Gaming discussions',
|
|
|
|
|
'nsfw' => false
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
], 200)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
$result = $service->listCommunities(
|
|
|
|
|
'test-token',
|
|
|
|
|
'All',
|
|
|
|
|
'TopMonth',
|
|
|
|
|
25,
|
|
|
|
|
2,
|
|
|
|
|
true
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$this->assertArrayHasKey('communities', $result);
|
|
|
|
|
$this->assertCount(1, $result['communities']);
|
|
|
|
|
$this->assertEquals('gaming', $result['communities'][0]['community']['name']);
|
|
|
|
|
|
|
|
|
|
Http::assertSent(function ($request) {
|
|
|
|
|
return str_contains($request->url(), '/api/v3/community/list')
|
|
|
|
|
&& str_contains($request->url(), 'type_=All')
|
|
|
|
|
&& str_contains($request->url(), 'sort=TopMonth')
|
|
|
|
|
&& str_contains($request->url(), 'limit=25')
|
|
|
|
|
&& str_contains($request->url(), 'page=2')
|
|
|
|
|
&& str_contains($request->url(), 'show_nsfw=1')
|
|
|
|
|
&& $request->header('Authorization')[0] === 'Bearer test-token';
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_list_communities_success_without_token(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'*' => Http::response([
|
|
|
|
|
'communities' => []
|
|
|
|
|
], 200)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
$result = $service->listCommunities();
|
|
|
|
|
|
|
|
|
|
$this->assertArrayHasKey('communities', $result);
|
|
|
|
|
$this->assertEmpty($result['communities']);
|
|
|
|
|
|
|
|
|
|
Http::assertSent(function ($request) {
|
|
|
|
|
return !$request->hasHeader('Authorization');
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_list_communities_throws_on_unsuccessful_response(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'*' => Http::response('Server Error', 500)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
Log::shouldReceive('warning')->once()->with('Failed to fetch communities list', Mockery::any());
|
|
|
|
|
Log::shouldReceive('error')->once()->with('Exception while fetching communities list', Mockery::any());
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
|
|
|
|
|
$this->expectException(Exception::class);
|
|
|
|
|
$this->expectExceptionMessage('Failed to fetch communities list: 500 - Server Error');
|
|
|
|
|
|
|
|
|
|
$service->listCommunities('token');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_list_communities_throws_on_404_response(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'*' => Http::response('Not Found', 404)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
Log::shouldReceive('warning')->once();
|
|
|
|
|
Log::shouldReceive('error')->once();
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
|
|
|
|
|
$this->expectException(Exception::class);
|
|
|
|
|
$this->expectExceptionMessage('Failed to fetch communities list: 404');
|
|
|
|
|
|
|
|
|
|
$service->listCommunities('token');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_list_communities_returns_empty_communities_on_invalid_response_format(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'*' => Http::response([
|
|
|
|
|
'invalid_format' => 'data'
|
|
|
|
|
], 200)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
Log::shouldReceive('warning')->once()->with('Invalid communities list response format', Mockery::any());
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
$result = $service->listCommunities();
|
|
|
|
|
|
|
|
|
|
$this->assertArrayHasKey('communities', $result);
|
|
|
|
|
$this->assertEmpty($result['communities']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_list_communities_handles_exception(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake(function () {
|
|
|
|
|
throw new Exception('Network error');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Log::shouldReceive('error')->once()->with('Exception while fetching communities list', Mockery::any());
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
|
|
|
|
|
$this->expectException(Exception::class);
|
|
|
|
|
$this->expectExceptionMessage('Network error');
|
|
|
|
|
|
|
|
|
|
$service->listCommunities('token');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_list_communities_with_all_sort_options(): void
|
|
|
|
|
{
|
|
|
|
|
$sortOptions = ['Hot', 'Active', 'New', 'TopDay', 'TopWeek', 'TopMonth', 'TopYear', 'TopAll'];
|
|
|
|
|
|
|
|
|
|
foreach ($sortOptions as $sort) {
|
|
|
|
|
Http::fake([
|
|
|
|
|
'*' => Http::response(['communities' => []], 200)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
$result = $service->listCommunities(null, 'Local', $sort);
|
|
|
|
|
|
|
|
|
|
$this->assertArrayHasKey('communities', $result);
|
|
|
|
|
|
|
|
|
|
Http::assertSent(function ($request) use ($sort) {
|
|
|
|
|
return str_contains($request->url(), "sort={$sort}");
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_list_communities_with_all_type_options(): void
|
|
|
|
|
{
|
|
|
|
|
$typeOptions = ['Local', 'All', 'Subscribed'];
|
|
|
|
|
|
|
|
|
|
foreach ($typeOptions as $type) {
|
|
|
|
|
Http::fake([
|
|
|
|
|
'*' => Http::response(['communities' => []], 200)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
$result = $service->listCommunities(null, $type);
|
|
|
|
|
|
|
|
|
|
$this->assertArrayHasKey('communities', $result);
|
|
|
|
|
|
|
|
|
|
Http::assertSent(function ($request) use ($type) {
|
|
|
|
|
return str_contains($request->url(), "type_={$type}");
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_list_communities_pagination_parameters(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'*' => Http::response(['communities' => []], 200)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
$result = $service->listCommunities(null, 'Local', 'Active', 100, 3);
|
|
|
|
|
|
|
|
|
|
$this->assertArrayHasKey('communities', $result);
|
|
|
|
|
|
|
|
|
|
Http::assertSent(function ($request) {
|
|
|
|
|
return str_contains($request->url(), 'limit=100')
|
|
|
|
|
&& str_contains($request->url(), 'page=3');
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_list_communities_nsfw_parameter(): void
|
|
|
|
|
{
|
|
|
|
|
Http::fake([
|
|
|
|
|
'*' => Http::response(['communities' => []], 200)
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$service = new LemmyApiService('lemmy.world');
|
|
|
|
|
|
|
|
|
|
// Test with NSFW enabled
|
|
|
|
|
$result = $service->listCommunities(null, 'Local', 'Active', 50, 1, true);
|
|
|
|
|
$this->assertArrayHasKey('communities', $result);
|
|
|
|
|
|
|
|
|
|
Http::assertSent(function ($request) {
|
|
|
|
|
return str_contains($request->url(), 'show_nsfw=1');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Test with NSFW disabled
|
|
|
|
|
$result = $service->listCommunities(null, 'Local', 'Active', 50, 1, false);
|
|
|
|
|
$this->assertArrayHasKey('communities', $result);
|
|
|
|
|
|
|
|
|
|
Http::assertSent(function ($request) {
|
|
|
|
|
return str_contains($request->url(), 'show_nsfw=');
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-08-11 18:26:00 +02:00
|
|
|
}
|