Upgrade to Laravel 13

This commit is contained in:
Jonny Barnes 2026-04-07 09:01:19 +01:00
commit 9f012b01e4
Signed by: jonny
SSH key fingerprint: SHA256:CTuSlns5U7qlD9jqHvtnVmfYV3Zwl2Z7WnJ4/dqOaL8
117 changed files with 1878 additions and 2215 deletions

View file

@ -31,7 +31,7 @@ class ArticlesTest extends TestCase
$article = new Article;
$article->main = 'Some *markdown*';
$this->assertEquals('<p>Some <em>markdown</em></p>' . PHP_EOL, $article->html);
$this->assertEquals('<p>Some <em>markdown</em></p>'.PHP_EOL, $article->html);
}
#[Test]
@ -58,7 +58,7 @@ class ArticlesTest extends TestCase
$article->title = 'Test Title';
$this->assertEquals(
'/blog/' . date('Y') . '/' . date('m') . '/test',
'/blog/'.date('Y').'/'.date('m').'/test',
$article->link
);
}

View file

@ -18,8 +18,8 @@ class DownloadWebMentionJobTest extends TestCase
protected function tearDown(): void
{
$fs = new FileSystem;
if ($fs->exists(storage_path() . '/HTML/https')) {
$fs->deleteDirectory(storage_path() . '/HTML/https');
if ($fs->exists(storage_path().'/HTML/https')) {
$fs->deleteDirectory(storage_path().'/HTML/https');
}
parent::tearDown();
}
@ -34,7 +34,7 @@ class DownloadWebMentionJobTest extends TestCase
<a class="u-like-of" href=""></a>
</div>
HTML;
$html = str_replace('href=""', 'href="' . config('app.url') . '/notes/A"', $html);
$html = str_replace('href=""', 'href="'.config('app.url').'/notes/A"', $html);
$mock = new MockHandler([
new Response(200, ['X-Foo' => 'Bar'], $html),
new Response(200, ['X-Foo' => 'Bar'], $html),
@ -49,7 +49,7 @@ class DownloadWebMentionJobTest extends TestCase
$job->handle($client);
$this->assertFileDoesNotExist(storage_path('HTML/https/example.org/reply') . '/1.' . date('Y-m-d') . '.backup');
$this->assertFileDoesNotExist(storage_path('HTML/https/example.org/reply').'/1.'.date('Y-m-d').'.backup');
}
#[Test]
@ -68,8 +68,8 @@ class DownloadWebMentionJobTest extends TestCase
<a class="u-repost-of" href=""></a>
</div>
HTML;
$html = str_replace('href=""', 'href="' . config('app.url') . '/notes/A"', $html);
$html2 = str_replace('href=""', 'href="' . config('app.url') . '/notes/A"', $html2);
$html = str_replace('href=""', 'href="'.config('app.url').'/notes/A"', $html);
$html2 = str_replace('href=""', 'href="'.config('app.url').'/notes/A"', $html2);
$mock = new MockHandler([
new Response(200, ['X-Foo' => 'Bar'], $html),
new Response(200, ['X-Foo' => 'Bar'], $html2),
@ -84,7 +84,7 @@ class DownloadWebMentionJobTest extends TestCase
$job->handle($client);
$this->assertFileExists(storage_path('HTML/https/example.org/reply') . '/1.' . date('Y-m-d') . '.backup');
$this->assertFileExists(storage_path('HTML/https/example.org/reply').'/1.'.date('Y-m-d').'.backup');
}
#[Test]
@ -97,7 +97,7 @@ class DownloadWebMentionJobTest extends TestCase
<a class="u-like-of" href=""></a>
</div>
HTML;
$html = str_replace('href=""', 'href="' . config('app.url') . '/notes/A"', $html);
$html = str_replace('href=""', 'href="'.config('app.url').'/notes/A"', $html);
$mock = new MockHandler([
new Response(200, ['X-Foo' => 'Bar'], $html),
]);

View file

@ -20,18 +20,18 @@ class ProcessMediaJobTest extends TestCase
$job = new ProcessMedia('file.txt');
$job->handle($manager);
$this->assertFileDoesNotExist(storage_path('app/media/') . 'file.txt');
$this->assertFileDoesNotExist(storage_path('app/media/').'file.txt');
}
#[Test]
public function small_images_are_not_resized(): void
{
$manager = app()->make(ImageManager::class);
Storage::disk('local')->put('media/aaron.png', file_get_contents(__DIR__ . '/../../aaron.png'));
Storage::disk('local')->put('media/aaron.png', file_get_contents(__DIR__.'/../../aaron.png'));
$job = new ProcessMedia('aaron.png');
$job->handle($manager);
$this->assertFileDoesNotExist(storage_path('app/media/') . 'aaron.png');
$this->assertFileDoesNotExist(storage_path('app/media/').'aaron.png');
// Tidy up files created by the job
Storage::disk('local')->delete('public/media/aaron.png');
@ -51,7 +51,7 @@ class ProcessMediaJobTest extends TestCase
Storage::disk('public')->assertExists('media/test-image-small.jpg');
Storage::disk('public')->assertExists('media/test-image-medium.jpg');
$this->assertFileDoesNotExist(storage_path('app/media/') . 'test-image.jpg');
$this->assertFileDoesNotExist(storage_path('app/media/').'test-image.jpg');
// Tidy up files created by the job
Storage::disk('public')->delete('media/test-image.jpg');

View file

@ -27,8 +27,8 @@ class ProcessWebMentionJobTest extends TestCase
protected function tearDown(): void
{
$fs = new FileSystem;
if ($fs->exists(storage_path() . '/HTML/https')) {
$fs->deleteDirectory(storage_path() . '/HTML/https');
if ($fs->exists(storage_path().'/HTML/https')) {
$fs->deleteDirectory(storage_path().'/HTML/https');
}
parent::tearDown();
}
@ -64,7 +64,7 @@ class ProcessWebMentionJobTest extends TestCase
I liked <a class="u-like-of" href="/notes/1">a note</a>.
</div>
HTML;
$html = str_replace('href="', 'href="' . config('app.url'), $html);
$html = str_replace('href="', 'href="'.config('app.url'), $html);
$mock = new MockHandler([
new Response(200, [], $html),
]);
@ -117,7 +117,7 @@ class ProcessWebMentionJobTest extends TestCase
'source' => $source,
'type' => 'in-reply-to',
// phpcs:ignore Generic.Files.LineLength.TooLong
'mf2' => '{"rels": [], "items": [{"type": ["h-entry"], "properties": {"content": [{"html": "Updated reply", "value": "Updated reply"}], "in-reply-to": ["' . $note->uri . '"]}}], "rel-urls": []}',
'mf2' => '{"rels": [], "items": [{"type": ["h-entry"], "properties": {"content": [{"html": "Updated reply", "value": "Updated reply"}], "in-reply-to": ["'.$note->uri.'"]}}], "rel-urls": []}',
]);
}
@ -142,7 +142,7 @@ class ProcessWebMentionJobTest extends TestCase
$source = 'https://example.org/reply/1';
$webmention = new WebMention;
$webmention->source = $source;
$webmention->target = config('app.url') . '/notes/E';
$webmention->target = config('app.url').'/notes/E';
$webmention->type = 'in-reply-to';
$webmention->save();
@ -179,7 +179,7 @@ class ProcessWebMentionJobTest extends TestCase
$source = 'https://example.org/reply/1';
$webmention = new WebMention;
$webmention->source = $source;
$webmention->target = config('app.url') . '/notes/E';
$webmention->target = config('app.url').'/notes/E';
$webmention->type = 'like-of';
$webmention->save();
@ -207,7 +207,7 @@ class ProcessWebMentionJobTest extends TestCase
I liked <a class="u-like-of" href="/notes/1">a note</a>.
</div>
HTML;
$html = str_replace('href="', 'href="' . config('app.url'), $html);
$html = str_replace('href="', 'href="'.config('app.url'), $html);
$mock = new MockHandler([
new Response(200, [], $html),
]);
@ -248,7 +248,7 @@ class ProcessWebMentionJobTest extends TestCase
$source = 'https://example.org/reply/1';
$webmention = new WebMention;
$webmention->source = $source;
$webmention->target = config('app.url') . '/notes/E';
$webmention->target = config('app.url').'/notes/E';
$webmention->type = 'repost-of';
$webmention->save();

View file

@ -18,9 +18,9 @@ class SaveProfileImageJobTest extends TestCase
{
protected function tearDown(): void
{
if (file_exists(public_path() . '/assets/profile-images/example.org/image')) {
unlink(public_path() . '/assets/profile-images/example.org/image');
rmdir(public_path() . '/assets/profile-images/example.org');
if (file_exists(public_path().'/assets/profile-images/example.org/image')) {
unlink(public_path().'/assets/profile-images/example.org/image');
rmdir(public_path().'/assets/profile-images/example.org');
}
parent::tearDown();
}
@ -77,7 +77,7 @@ class SaveProfileImageJobTest extends TestCase
$job = new SaveProfileImage($mf);
$job->handle($authorship);
$this->assertFileExists(public_path() . '/assets/profile-images/example.org/image');
$this->assertFileExists(public_path().'/assets/profile-images/example.org/image');
}
#[Test]
@ -103,8 +103,8 @@ class SaveProfileImageJobTest extends TestCase
$job = new SaveProfileImage($mf);
$job->handle($authorship);
$this->assertFileEquals(
public_path() . '/assets/profile-images/default-image',
public_path() . '/assets/profile-images/example.org/image'
public_path().'/assets/profile-images/default-image',
public_path().'/assets/profile-images/example.org/image'
);
}
@ -133,7 +133,7 @@ class SaveProfileImageJobTest extends TestCase
$job = new SaveProfileImage($mf);
$job->handle($authorship);
$this->assertFileExists(public_path() . '/assets/profile-images/example.org/image');
$this->assertFileExists(public_path().'/assets/profile-images/example.org/image');
}
#[Test]
@ -164,6 +164,6 @@ class SaveProfileImageJobTest extends TestCase
$job = new SaveProfileImage($mf);
$job->handle($authorship);
$this->assertFileExists(public_path() . '/assets/profile-images/example.org/image');
$this->assertFileExists(public_path().'/assets/profile-images/example.org/image');
}
}

View file

@ -7,6 +7,7 @@ namespace Tests\Unit\Jobs;
use App\Jobs\SaveScreenshot;
use App\Models\Bookmark;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
@ -27,7 +28,7 @@ class SaveScreenshotJobTest extends TestCase
$guzzleMock = new MockHandler([
new Response(201, ['Content-Type' => 'application/json'], '{"data":{"id":"68d52633-e170-465e-b13e-746c97d01ffb","job_id":null,"status":"finished","credits":null,"code":null,"message":null,"percent":100,"operation":"capture-website","engine":"chrome","engine_version":"107","result":null,"created_at":"2023-01-07T21:05:48+00:00","started_at":null,"ended_at":null,"retry_of_task_id":null,"copy_of_task_id":null,"user_id":61485254,"priority":-10,"host_name":null,"storage":"ceph-fra","depends_on_task_ids":[],"links":{"self":"https:\/\/api.cloudconvert.com\/v2\/tasks\/68d52633-e170-465e-b13e-746c97d01ffb"}}}'),
new Response(201, ['Content-Type' => 'application/json'], '{"data":{"id":"27f33137-cc03-4468-aba4-1e1aa8c096fb","job_id":null,"status":"finished","credits":null,"code":null,"message":null,"percent":100,"operation":"export\/url","result":null,"created_at":"2023-01-07T21:10:02+00:00","started_at":null,"ended_at":null,"retry_of_task_id":null,"copy_of_task_id":null,"user_id":61485254,"priority":-10,"host_name":null,"storage":"ceph-fra","depends_on_task_ids":["68d52633-e170-465e-b13e-746c97d01ffb"],"links":{"self":"https:\/\/api.cloudconvert.com\/v2\/tasks\/27f33137-cc03-4468-aba4-1e1aa8c096fb"}}}'),
new Response(200, ['Content-Type' => 'image/png'], fopen(__DIR__ . '/../../theverge.com.png', 'rb')),
new Response(200, ['Content-Type' => 'image/png'], fopen(__DIR__.'/../../theverge.com.png', 'rb')),
]);
$guzzleHandler = HandlerStack::create($guzzleMock);
$guzzleClient = new Client(['handler' => $guzzleHandler]);
@ -45,7 +46,7 @@ class SaveScreenshotJobTest extends TestCase
}
// Retry connection exceptions
if ($exception instanceof \GuzzleHttp\Exception\ConnectException) {
if ($exception instanceof ConnectException) {
return true;
}
@ -82,7 +83,7 @@ class SaveScreenshotJobTest extends TestCase
$bookmark->refresh();
$this->assertEquals('68d52633-e170-465e-b13e-746c97d01ffb', $bookmark->screenshot);
Storage::disk('public')->assertExists('/assets/img/bookmarks/' . $bookmark->screenshot . '.png');
Storage::disk('public')->assertExists('/assets/img/bookmarks/'.$bookmark->screenshot.'.png');
}
#[Test]
@ -92,7 +93,7 @@ class SaveScreenshotJobTest extends TestCase
$guzzleMock = new MockHandler([
new Response(201, ['Content-Type' => 'application/json'], '{"id":1,"data":{"id":"68d52633-e170-465e-b13e-746c97d01ffb","job_id":null,"status":"waiting","credits":null,"code":null,"message":null,"percent":100,"operation":"capture-website","engine":"chrome","engine_version":"107","result":null,"created_at":"2023-01-07T21:05:48+00:00","started_at":null,"ended_at":null,"retry_of_task_id":null,"copy_of_task_id":null,"user_id":61485254,"priority":-10,"host_name":null,"storage":"ceph-fra","depends_on_task_ids":[],"links":{"self":"https:\/\/api.cloudconvert.com\/v2\/tasks\/68d52633-e170-465e-b13e-746c97d01ffb"}}}'),
new Response(201, ['Content-Type' => 'application/json'], '{"id":2,"data":{"id":"27f33137-cc03-4468-aba4-1e1aa8c096fb","job_id":null,"status":"waiting","credits":null,"code":null,"message":null,"percent":100,"operation":"export\/url","result":null,"created_at":"2023-01-07T21:10:02+00:00","started_at":null,"ended_at":null,"retry_of_task_id":null,"copy_of_task_id":null,"user_id":61485254,"priority":-10,"host_name":null,"storage":"ceph-fra","depends_on_task_ids":["68d52633-e170-465e-b13e-746c97d01ffb"],"links":{"self":"https:\/\/api.cloudconvert.com\/v2\/tasks\/27f33137-cc03-4468-aba4-1e1aa8c096fb"}}}'),
new Response(200, ['Content-Type' => 'image/png'], fopen(__DIR__ . '/../../theverge.com.png', 'rb')),
new Response(200, ['Content-Type' => 'image/png'], fopen(__DIR__.'/../../theverge.com.png', 'rb')),
]);
$guzzleHandler = HandlerStack::create($guzzleMock);
$guzzleClient = new Client(['handler' => $guzzleHandler]);
@ -115,7 +116,7 @@ class SaveScreenshotJobTest extends TestCase
}
// Retry connection exceptions
if ($exception instanceof \GuzzleHttp\Exception\ConnectException) {
if ($exception instanceof ConnectException) {
return true;
}
@ -152,7 +153,7 @@ class SaveScreenshotJobTest extends TestCase
$bookmark->refresh();
$this->assertEquals('68d52633-e170-465e-b13e-746c97d01ffb', $bookmark->screenshot);
Storage::disk('public')->assertExists('/assets/img/bookmarks/' . $bookmark->screenshot . '.png');
Storage::disk('public')->assertExists('/assets/img/bookmarks/'.$bookmark->screenshot.'.png');
// Also assert we made the correct number of requests
$this->assertCount(2, $container);
// However with retries there should be more than 4 responses for the 2 requests

View file

@ -29,7 +29,7 @@ class SendWebMentionJobTest extends TestCase
{
$url = 'https://example.org/webmention';
$mock = new MockHandler([
new Response(200, ['Link' => '<' . $url . '>; rel="webmention"']),
new Response(200, ['Link' => '<'.$url.'>; rel="webmention"']),
]);
$handler = HandlerStack::create($mock);
$client = new Client(['handler' => $handler]);

View file

@ -25,7 +25,7 @@ class SyndicateNoteToBlueskyJobTest extends TestCase
$faker = Factory::create();
$randomNumber = $faker->randomNumber();
$mock = new MockHandler([
new Response(201, ['Location' => 'https://bsky.app/profile/jonnybarnes.uk/' . $randomNumber]),
new Response(201, ['Location' => 'https://bsky.app/profile/jonnybarnes.uk/'.$randomNumber]),
]);
$handler = HandlerStack::create($mock);
$client = new Client(['handler' => $handler]);
@ -35,7 +35,7 @@ class SyndicateNoteToBlueskyJobTest extends TestCase
$job->handle($client);
$this->assertDatabaseHas('notes', [
'bluesky_url' => 'https://bsky.app/profile/jonnybarnes.uk/' . $randomNumber,
'bluesky_url' => 'https://bsky.app/profile/jonnybarnes.uk/'.$randomNumber,
]);
}
@ -49,7 +49,7 @@ class SyndicateNoteToBlueskyJobTest extends TestCase
$container = [];
$history = Middleware::history($container);
$mock = new MockHandler([
new Response(201, ['Location' => 'https://bsky.app/profile/jonnybarnes.uk/' . $randomNumber]),
new Response(201, ['Location' => 'https://bsky.app/profile/jonnybarnes.uk/'.$randomNumber]),
]);
$handler = HandlerStack::create($mock);
$handler->push($history);
@ -60,7 +60,7 @@ class SyndicateNoteToBlueskyJobTest extends TestCase
$job->handle($client);
$this->assertDatabaseHas('notes', [
'bluesky_url' => 'https://bsky.app/profile/jonnybarnes.uk/' . $randomNumber,
'bluesky_url' => 'https://bsky.app/profile/jonnybarnes.uk/'.$randomNumber,
]);
$expectedRequestContent = '{"type":["h-entry"],"properties":{"content":["This is a **test**"]}}';

View file

@ -25,7 +25,7 @@ class SyndicateNoteToMastodonJobTest extends TestCase
$faker = Factory::create();
$randomNumber = $faker->randomNumber();
$mock = new MockHandler([
new Response(201, ['Location' => 'https://mastodon.example/@jonny/' . $randomNumber]),
new Response(201, ['Location' => 'https://mastodon.example/@jonny/'.$randomNumber]),
]);
$handler = HandlerStack::create($mock);
$client = new Client(['handler' => $handler]);
@ -35,7 +35,7 @@ class SyndicateNoteToMastodonJobTest extends TestCase
$job->handle($client);
$this->assertDatabaseHas('notes', [
'mastodon_url' => 'https://mastodon.example/@jonny/' . $randomNumber,
'mastodon_url' => 'https://mastodon.example/@jonny/'.$randomNumber,
]);
}
@ -49,7 +49,7 @@ class SyndicateNoteToMastodonJobTest extends TestCase
$container = [];
$history = Middleware::history($container);
$mock = new MockHandler([
new Response(201, ['Location' => 'https://mastodon.example/@jonny/' . $randomNumber]),
new Response(201, ['Location' => 'https://mastodon.example/@jonny/'.$randomNumber]),
]);
$handler = HandlerStack::create($mock);
$handler->push($history);
@ -60,7 +60,7 @@ class SyndicateNoteToMastodonJobTest extends TestCase
$job->handle($client);
$this->assertDatabaseHas('notes', [
'mastodon_url' => 'https://mastodon.example/@jonny/' . $randomNumber,
'mastodon_url' => 'https://mastodon.example/@jonny/'.$randomNumber,
]);
$expectedRequestContent = '{"type":["h-entry"],"properties":{"content":["This is a **test**"]}}';

View file

@ -7,6 +7,7 @@ namespace Tests\Unit;
use App\Models\Media;
use App\Models\Note;
use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
@ -38,4 +39,68 @@ class MediaTest extends TestCase
$this->assertEquals($absoluteUrl, $media->url);
}
#[Test]
public function local_paths_get_storage_url_prepended(): void
{
$media = new Media;
$media->path = 'photo.jpg';
$this->assertEquals(config('app.url').'/storage/photo.jpg', $media->url);
}
#[Test]
public function medium_url_returns_resized_path(): void
{
$media = new Media;
$media->path = 'photo.jpg';
$this->assertEquals(config('app.url').'/storage/photo-medium.jpg', $media->mediumurl);
}
#[Test]
public function small_url_returns_resized_path(): void
{
$media = new Media;
$media->path = 'photo.jpg';
$this->assertEquals(config('app.url').'/storage/photo-small.jpg', $media->smallurl);
}
#[Test]
public function size_url_handles_dotted_basename(): void
{
$media = new Media;
$media->path = 'file.name.png';
$this->assertEquals(config('app.url').'/storage/file.name-medium.png', $media->mediumurl);
}
/**
* @dataProvider mimeTypeProvider
*/
#[DataProvider('mimeTypeProvider')]
public function mimetype_returns_correct_mime_for_extension(string $path, string $expected): void
{
$media = new Media;
$media->path = $path;
$this->assertEquals($expected, $media->mimetype);
}
public static function mimeTypeProvider(): array
{
return [
['photo.gif', 'image/gif'],
['photo.jpeg', 'image/jpeg'],
['photo.jpg', 'image/jpeg'],
['photo.png', 'image/png'],
['photo.svg', 'image/svg+xml'],
['photo.tiff', 'image/tiff'],
['photo.webp', 'image/webp'],
['video.mp4', 'video/mp4'],
['video.mkv', 'video/mkv'],
['file.bin', 'application/octet-stream'],
];
}
}

View file

@ -0,0 +1,110 @@
<?php
declare(strict_types=1);
namespace Tests\Unit;
use App\Services\Micropub\Data\UpdateData;
use Illuminate\Http\Request;
use JsonException;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
class MicropubUpdateDataTest extends TestCase
{
/**
* @throws JsonException
*/
#[Test]
public function from_request_parses_json_body(): void
{
$request = Request::create('/micropub', 'POST', [], [], [], [
'CONTENT_TYPE' => 'application/json',
], json_encode([
'token_data' => ['me' => 'https://example.com'],
'url' => 'https://example.com/notes/1',
'replace' => ['content' => ['new content']],
'add' => ['syndication' => ['https://twitter.com']],
'delete' => ['category' => ['old-tag']],
], JSON_THROW_ON_ERROR));
$dto = UpdateData::fromRequest($request);
$this->assertEquals(['me' => 'https://example.com'], $dto->tokenData);
$this->assertEquals('https://example.com/notes/1', $dto->updateUrl);
$this->assertEquals(['content' => ['new content']], $dto->updateReplace);
$this->assertEquals(['syndication' => ['https://twitter.com']], $dto->updateAdd);
$this->assertEquals(['category' => ['old-tag']], $dto->updateDelete);
}
#[Test]
public function from_request_parses_form_encoded_body(): void
{
$request = Request::create('/micropub', 'POST', [
'token_data' => ['me' => 'https://example.com'],
'url' => 'https://example.com/notes/1',
'replace' => ['content' => ['new content']],
'add' => ['syndication' => ['https://twitter.com']],
'delete' => ['category' => ['old-tag']],
]);
$dto = UpdateData::fromRequest($request);
$this->assertEquals(['me' => 'https://example.com'], $dto->tokenData);
$this->assertEquals('https://example.com/notes/1', $dto->updateUrl);
$this->assertEquals(['content' => ['new content']], $dto->updateReplace);
$this->assertEquals(['syndication' => ['https://twitter.com']], $dto->updateAdd);
$this->assertEquals(['category' => ['old-tag']], $dto->updateDelete);
}
/**
* @throws JsonException
*/
#[Test]
public function from_request_nullable_fields_default_to_null(): void
{
$request = Request::create('/micropub', 'POST', [], [], [], [
'CONTENT_TYPE' => 'application/json',
], json_encode([
'token_data' => ['me' => 'https://example.com'],
'url' => 'https://example.com/notes/1',
], JSON_THROW_ON_ERROR));
$dto = UpdateData::fromRequest($request);
$this->assertNull($dto->updateReplace);
$this->assertNull($dto->updateAdd);
$this->assertNull($dto->updateDelete);
}
#[Test]
public function from_array_maps_all_fields(): void
{
$dto = UpdateData::fromArray([
'token_data' => ['me' => 'https://example.com'],
'update_url' => 'https://example.com/notes/1',
'update_replace' => ['content' => ['updated']],
'update_add' => ['category' => ['new-tag']],
'update_delete' => ['syndication' => ['https://old.example.com']],
]);
$this->assertEquals(['me' => 'https://example.com'], $dto->tokenData);
$this->assertEquals('https://example.com/notes/1', $dto->updateUrl);
$this->assertEquals(['content' => ['updated']], $dto->updateReplace);
$this->assertEquals(['category' => ['new-tag']], $dto->updateAdd);
$this->assertEquals(['syndication' => ['https://old.example.com']], $dto->updateDelete);
}
#[Test]
public function from_array_nullable_fields_default_to_null(): void
{
$dto = UpdateData::fromArray([
'token_data' => ['me' => 'https://example.com'],
]);
$this->assertNull($dto->updateUrl);
$this->assertNull($dto->updateReplace);
$this->assertNull($dto->updateAdd);
$this->assertNull($dto->updateDelete);
}
}

View file

@ -31,7 +31,7 @@ class NotesTest extends TestCase
public function get_note_attribute_method_calls_sub_methods(): void
{
// phpcs:ignore
$expected = '<p>Having a <a rel="tag" class="p-category" href="/notes/tagged/beer">#beer</a> at the local. 🍺</p>' . PHP_EOL;
$expected = '<p>Having a <a rel="tag" class="p-category" href="/notes/tagged/beer">#beer</a> at the local. 🍺</p>'.PHP_EOL;
$note = Note::factory([
'note' => 'Having a #beer at the local. 🍺',
])->create();
@ -53,7 +53,7 @@ class NotesTest extends TestCase
<img class="social-icon" src="/assets/img/social-icons/twitter.svg" alt=""> t
</a>
</span>
</span></p>' . PHP_EOL;
</span></p>'.PHP_EOL;
Contact::factory()->create([
'nick' => 'tantek',
'name' => 'Tantek Çelik',
@ -98,7 +98,7 @@ class NotesTest extends TestCase
<img class="social-icon" src="/assets/img/social-icons/facebook.svg" alt=""> Facebook
</a>
</span>
</span></p>' . PHP_EOL;
</span></p>'.PHP_EOL;
$this->assertEquals($expected, $note->note);
}
@ -108,7 +108,7 @@ class NotesTest extends TestCase
#[Test]
public function twitter_link_is_created_when_no_contact_found(): void
{
$expected = '<p>Hi <a href="https://twitter.com/bob">@bob</a></p>' . PHP_EOL;
$expected = '<p>Hi <a href="https://twitter.com/bob">@bob</a></p>'.PHP_EOL;
$note = Note::factory()->create([
'note' => 'Hi @bob',
]);
@ -312,7 +312,7 @@ class NotesTest extends TestCase
$note->media()->save($media);
$expected = 'A nice image
<img src="' . config('app.url') . '/storage/test.png" alt="">';
<img src="'.config('app.url').'/storage/test.png" alt="">';
$this->assertEquals($expected, $note->content);
}
@ -329,7 +329,7 @@ class NotesTest extends TestCase
$note->media()->save($media);
$expected = 'A nice video
<video src="' . config('app.url') . '/storage/test.mkv">';
<video src="'.config('app.url').'/storage/test.mkv">';
$this->assertEquals($expected, $note->content);
}
@ -346,7 +346,7 @@ class NotesTest extends TestCase
$note->media()->save($media);
$expected = 'Some nice audio
<audio src="' . config('app.url') . '/storage/test.flac">';
<audio src="'.config('app.url').'/storage/test.flac">';
$this->assertEquals($expected, $note->content);
}
@ -378,29 +378,11 @@ class NotesTest extends TestCase
]);
$this->assertSame(
'<p>The best search engine? <a href="https://kagi.com">https://kagi.com</a></p>' . PHP_EOL,
'<p>The best search engine? <a href="https://kagi.com">https://kagi.com</a></p>'.PHP_EOL,
$note->note
);
}
/**
* For now, just reply on a cached object instead of actually querying Twitter.
*/
#[Test]
public function check_in_reply_to_is_twitter_link(): void
{
$tempContent = (object) [
'html' => 'something random',
];
Cache::put('933662564587855877', $tempContent);
$note = Note::factory()->create([
'in_reply_to' => 'https://twitter.com/someRando/status/933662564587855877',
]);
$this->assertEquals($tempContent, $note->twitter);
}
#[Test]
public function latitude_and_longitude_can_be_parsed_from_plain_location(): void
{
@ -427,7 +409,7 @@ class NotesTest extends TestCase
#[Test]
public function mastodon_usernames_are_parsed_correctly(): void
{
$expected = '<p>Hi <a href="https://phpc.social/@freekmurze">@freekmurze@phpc.social</a> how are you?</p>' . PHP_EOL;
$expected = '<p>Hi <a href="https://phpc.social/@freekmurze">@freekmurze@phpc.social</a> how are you?</p>'.PHP_EOL;
$note = Note::factory()->create([
'note' => 'Hi @freekmurze@phpc.social how are you?',
]);

View file

@ -46,7 +46,7 @@ class PlacesTest extends TestCase
$place = Place::factory()->create([
'name' => 'The Bridgewater Pub',
]);
$this->assertEquals(config('app.url') . '/places/the-bridgewater-pub', $place->uri);
$this->assertEquals(config('app.url').'/places/the-bridgewater-pub', $place->uri);
}
#[Test]

View file

@ -6,10 +6,8 @@ namespace Tests\Unit;
use App\Models\Note;
use App\Models\WebMention;
use Codebird\Codebird;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
@ -82,41 +80,6 @@ class WebMentionTest extends TestCase
$this->assertEquals($expected, $webmention->createPhotoLink($twitterProfileImage));
}
#[Test]
public function create_photo_link_returns_cached_twitter_photo_links(): void
{
$webmention = new WebMention;
$twitterURL = 'https://twitter.com/example';
$expected = 'https://pbs.twimg.com/static_profile_link.jpg';
Cache::put($twitterURL, $expected, 1);
$this->assertEquals($expected, $webmention->createPhotoLink($twitterURL));
}
#[Test]
public function create_photo_link_resolves_twitter_photo_links(): void
{
$info = (object) [
'profile_image_url_https' => 'https://pbs.twimg.com/static_profile_link.jpg',
];
$codebirdMock = $this->createPartialMock(Codebird::class, ['__call']);
$codebirdMock->method('__call')
->with('users_show', $this->anything())
->willReturn($info);
$this->app->instance(Codebird::class, $codebirdMock);
Cache::shouldReceive('has')
->once()
->andReturn(false);
Cache::shouldReceive('put')
->once()
->andReturn(true);
$webmention = new WebMention;
$twitterURL = 'https://twitter.com/example';
$expected = 'https://pbs.twimg.com/static_profile_link.jpg';
$this->assertEquals($expected, $webmention->createPhotoLink($twitterURL));
}
#[Test]
public function get_reply_attribute_defaults_to_null(): void
{
@ -131,4 +94,37 @@ class WebMentionTest extends TestCase
$webmention->mf2 = json_encode(['no_html' => 'found_here']);
$this->assertNull($webmention->reply);
}
#[Test]
public function author_attribute_returns_null_when_mf2_is_null(): void
{
$webmention = new WebMention;
$webmention->mf2 = null;
$this->assertNull($webmention->author);
}
#[Test]
public function author_attribute_returns_hcard_without_photo_key_when_no_photo_present(): void
{
$webmention = new WebMention;
$webmention->mf2 = json_encode([
'items' => [[
'type' => ['h-entry'],
'properties' => [
'author' => [[
'type' => ['h-card'],
'properties' => [
'name' => ['Test Person'],
'url' => ['https://example.com'],
],
]],
'content' => ['hello'],
],
]],
]);
$hCard = $webmention->author;
$this->assertNotNull($hCard);
$this->assertArrayNotHasKey('photo', $hCard['properties'] ?? []);
}
}