150 lines
4.7 KiB
PHP
150 lines
4.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Lvl0\FediDiscover\Tests\Feature;
|
|
|
|
use Illuminate\Support\Facades\Http;
|
|
use Lvl0\FediDiscover\Clients\LemmyClient;
|
|
use Lvl0\FediDiscover\Config\InstanceType;
|
|
use Lvl0\FediDiscover\Models\Instance;
|
|
use Lvl0\FediDiscover\ValueObjects\FediversePost;
|
|
use Tests\TestCase;
|
|
|
|
class LemmyClientTest extends TestCase
|
|
{
|
|
public function test_it_maps_each_post_to_a_fediverse_post(): void
|
|
{
|
|
Http::fake([
|
|
'*' => Http::response([
|
|
'posts' => [
|
|
$this->lemmyPost(
|
|
id: 42,
|
|
apId: 'https://lemmy.world/post/42',
|
|
name: 'My Great Post',
|
|
body: 'Some body text',
|
|
published: '2026-04-25T10:00:00.000000',
|
|
),
|
|
],
|
|
], 200),
|
|
]);
|
|
|
|
$posts = (new LemmyClient)->fetchPostsSince($this->lemmyInstance(), null);
|
|
|
|
$this->assertCount(1, $posts);
|
|
$this->assertInstanceOf(FediversePost::class, $posts->first());
|
|
$this->assertSame('42', $posts->first()->cursorId);
|
|
$this->assertSame('https://lemmy.world/post/42', $posts->first()->selfUrl);
|
|
$this->assertSame('My Great Post', $posts->first()->title);
|
|
$this->assertSame('Some body text', $posts->first()->body);
|
|
$this->assertSame('2026-04-25T10:00:00.000000', $posts->first()->publishedAt);
|
|
}
|
|
|
|
public function test_url_field_is_appended_to_body(): void
|
|
{
|
|
Http::fake([
|
|
'*' => Http::response([
|
|
'posts' => [
|
|
$this->lemmyPost(
|
|
id: 42,
|
|
apId: 'https://lemmy.world/post/42',
|
|
url: 'https://example-garden.blog/post-42',
|
|
body: 'Some original text.',
|
|
),
|
|
],
|
|
], 200),
|
|
]);
|
|
|
|
$post = (new LemmyClient)->fetchPostsSince($this->lemmyInstance(), null)->first();
|
|
|
|
$this->assertStringContainsString('Some original text.', $post->body);
|
|
$this->assertStringContainsString('https://example-garden.blog/post-42', $post->body);
|
|
}
|
|
|
|
public function test_url_absent_leaves_body_clean(): void
|
|
{
|
|
Http::fake([
|
|
'*' => Http::response([
|
|
'posts' => [
|
|
$this->lemmyPost(
|
|
id: 7,
|
|
apId: 'https://lemmy.world/post/7',
|
|
body: 'Just a regular post.',
|
|
),
|
|
],
|
|
], 200),
|
|
]);
|
|
|
|
$post = (new LemmyClient)->fetchPostsSince($this->lemmyInstance(), null)->first();
|
|
|
|
$this->assertSame('Just a regular post.', $post->body);
|
|
}
|
|
|
|
public function test_it_handles_posts_without_a_body_key(): void
|
|
{
|
|
Http::fake([
|
|
'*' => Http::response([
|
|
'posts' => [
|
|
[
|
|
'post' => [
|
|
'id' => 99,
|
|
'ap_id' => 'https://lemmy.world/post/99',
|
|
'url' => null,
|
|
'name' => 'Link-only post',
|
|
'published' => '2026-04-25T10:00:00.000000',
|
|
// 'body' key intentionally absent — real Lemmy API omits it for link-only posts
|
|
],
|
|
],
|
|
],
|
|
], 200),
|
|
]);
|
|
|
|
$post = (new LemmyClient)->fetchPostsSince($this->lemmyInstance(), null)->first();
|
|
|
|
$this->assertNull($post->body);
|
|
}
|
|
|
|
public function test_it_hits_the_post_list_endpoint_of_the_instance(): void
|
|
{
|
|
Http::fake([
|
|
'lemmy.world/api/v3/post/list*' => Http::response(['posts' => []], 200),
|
|
]);
|
|
|
|
(new LemmyClient)->fetchPostsSince($this->lemmyInstance(), null);
|
|
|
|
Http::assertSent(fn ($request) => str_starts_with($request->url(), 'https://lemmy.world/api/v3/post/list')
|
|
&& $request->method() === 'GET'
|
|
);
|
|
}
|
|
|
|
private function lemmyInstance(): Instance
|
|
{
|
|
return new Instance([
|
|
'type' => InstanceType::Lemmy,
|
|
'url' => 'https://lemmy.world',
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* @return array<string, mixed>
|
|
*/
|
|
private function lemmyPost(
|
|
int $id,
|
|
string $apId,
|
|
?string $url = null,
|
|
string $body = '',
|
|
string $name = 'A post title',
|
|
string $published = '2026-04-25T10:00:00.000000',
|
|
): array {
|
|
return [
|
|
'post' => [
|
|
'id' => $id,
|
|
'ap_id' => $apId,
|
|
'url' => $url,
|
|
'body' => $body,
|
|
'name' => $name,
|
|
'published' => $published,
|
|
],
|
|
];
|
|
}
|
|
}
|